Skip to main content

How Plugins Run

Let's discuss how plugins run inside Figma.

As mentioned previously, plugins are written using JavaScript, HTML and CSS. This exposes a very browser-like environment. It is, however, important to note that writing JavaScript for a Figma plugin has some differences from writing JavaScript for a website.

In order for a plugin system to be secure and stable, some browser APIs are unavailable or need to be accessed differently. This is imporant to understand so you can answer questions like:

  • How do I access the contents of a Figma file?
  • How do I create a user interface for my plugin?
  • How do I make network requests?

For performance, we have decided to go with an execution model where plugin code runs on the main thread in a sandbox. The sandbox is a minimal JavaScript environment and does not expose browser APIs.

This means that you have all of standard JavaScript ES6+ available, including the standard types, the JSON and Promise APIs, binary types like Uint8Array, etc. We have also added a minimal version of the console API. But browser APIs like XMLHttpRequest and the DOM are not directly available from the sandbox.

To use browser APIs (e.g. to show UI), you need to create an <iframe> with a <script> tag inside. This can be done with figma.showUI(). Inside of this <iframe>, you can write any HTML/JavaScript and access any browser APIs.


To see the list of available JavaScript/Browser APIs on the main thread, run console.log(this) as the first line of your plugin.

The main thread can access the Figma "scene" (the hierarchy of layers that make up a Figma document) but not the browser APIs. Conversely, the iframe can access the browser APIs, but not the Figma scene. The main thread and the iframe can communicate with each other through message passing.

Additional network security is enforced if your plugin limits network access. When network access is limited, if your plugin attempts to access a domain that isn't specified in your plugin's manifest, Figma blocks that attempt and returns a content-security policy (CSP) error.

The enforcement of domain access is limited only to requests made by the plugin, such as Fetch API requests to a public REST API. If your plugin renders a website in an iframe, network access limits only apply directly to the website's domain. Network access limits do not affect resources needed by that website. For example, suppose your plugin frames and limits access only to Your plugin would be prevented from rendering content from other domains. However, would still be able to load external resources, such as scripts for Google Analytics.

When the plugin is finished with its work, it must call figma.closePlugin() to tell Figma that it is finished. Otherwise, the plugin will run indefinitely and the user will see a "Running [your plugin name]" visual bell until they close their browser tab.


Note that the user can cancel the plugin at any point by using the UI that Figma displays while the plugin is running. When this happens, Figma will itself call figma.closePlugin().