---
title: Customize and Build Your Own Plugins
short: Custom Plugins
type: plugins
category: Overview
cat: overview
order: 8
meta_title: Plugins Frequently Asked Questions
You can modify the plugin examples that we provide or build your own custom plugins.
Plugins are authored in JavaScript and are project-specific. They are limited to specific tasks and the annotation workflow and cannot, for example, be used to create new pages or otherwise extend the core functionality of Label Studio.
!!! note
Plugins are not available unless enabled. There are important security considerations to understand before requesting access.
Plugins are executed each time the annotation is displayed. For example, when you open a task, move between tasks, create a new annotation, switch between annotations, create a new annotation, and view older versions of the annotation.
This means that for each annotation you can add specific behavior. However, it also means that if you don’t plan accordingly when constructing your plugin logic, you could end up with repetitive actions.
To avoid multiple event subscriptions (and, consequently, multiple handler triggers), it is best to use LSI.on() because the handlers that are added using this method will be unsubscribed after the current annotation is closed. For more information on LSI, see below.
!!! note
Because plugins can be executed multiple times for the same annotation, you need to take measures to avoid issues such as infinite loops, memory leaks, and application crashes. For this reason, we recommend that each script run cleans up the previous run, meaning that event handlers should be stored in a global register along with their parameters so that they can be checked, stopped, or adjusted. Every handler should check whether it is still running over the current version of annotation/data in case it has changed.
However, handlers attached via `LSI.on()` are safe and will automatically handle this clean up process.
!!! info Tip
Plugins are executed within an asynchronous function, so you can use await as necessary.
It is important to test and refine plugins using a test project first to avoid any disruptions on live projects.
When you add a plugin, the Testing panel appears below the script field. You can use this to test the plugin with sample data, manually trigger events, and see what events are triggered as you interact with the sample data.
Note the following:
/project/:id API call).debugger to your script to have a convenient breakpoint to debug the plugin using your web browser’s developer tools.The Label Studio Interface (LSI) is a helper object that is designed to be used with plugins.
LSI simplifies access to some data and can perform special actions that only make sense within the framework of plugins.
LSI.import(url, integrity)Allows loading additional external scripts
| Parameter | Type | Description |
|---|---|---|
url |
string | Specifies the URL of an external script file. |
integrity |
string | Allows a browser to check the fetched script to ensure that the code is never loaded if the source has been manipulated. |
The method is asynchronous, so you can wait for the script to load before performing the main actions. For example:
await LSI.import('https://cdn.plot.ly/plotly-2.26.0.min.js', 'sha384-xuh4dD2xC9BZ4qOrUrLt8psbgevXF2v+K+FrXxV4MlJHnWKgnaKoh74vd/6Ik8uF');
console.log("Plotly is ready");
LSI.on(eventName, handler)Subscription to listen to events related to the Label Studio Frontend. Handlers attached/subscribed using this method will be unsubscribed when switching to another annotation. Any handlers inside this method should be secured manually.
For a list of all available events, see our Frontend reference.
!!! note
Top-level events such as labelStudioLoad and storageInitialized cannot be used with plugins, as they execute before the script is initialized.
| Parameter | Type | Description |
|---|---|---|
eventName |
string | A case-sensitive string representing the event type to listen for. |
handler |
function | A function that will be called when the event is triggered. This function can take arguments depending on the event. |
LSI.dataObjAlias to .task.data. This is the core data structure for a task, and includes the original data that needs to be annotated.
LSI.taskA getter that returns information about current task:
* id - ID of the task.
* data - Object representing task data.
LSI.annotationA getter that returns the currently selected annotation.
LSI.regionsA getter that returns all regions of the current annotation.
The following implementation details may be useful when creating your own plugins.
!!! note
While these details are relatively stable, we make no guarantees that they will not change in the future.
For more information on how annotations are stored and formatted, see How Label Studio saves results in annotations.
.areasMap of regions.
.regionsAn array of all regions (includes classifications).
.regionStore.regionsAn array of all real regions (excludes classifications).
.resultsArray of all results.
Note that this returns an array of objects with keys of all possible result types, but only one result type has an actual value. To access this value directly, use result.mainValue (which works as a shortcut for r[control.valueType]).
!!! note
region is retrieved by .region (see above).
region.labelingsArray of all labeling results for this region.
region.labelingThe first labeling result.
region.labelsAn array of label texts from labeling, but does not include other labeling results.
region.labelNameThe label text of the first label in the first labeling result.
region.labeling.selectedLabelsAn array of <Label> tags connected to every label in labeling.
For example, to retrieve the label color you can use region.labeling.selectedLabels[0].background.
region.labeling.getSelectedString(joinStr = " ")Returns a string with all labels in labeling. By default, these are concatenated with the param followed by a space (e.g. “A B”).
region.getLabelText()Returns a string with comma-separated list of labels in labeling, with optional text of the first per-region TextArea result. Formatted as follows: “A,B: text”