Figma plugins promise a streamlined workflow, empowering designers with custom tools embedded directly in their design environment. But behind the scenes, building a Figma plugin is often anything but seamless—especially when it comes to integrating external APIs. For many developers, the biggest culprit is a familiar one: CORS (Cross-Origin Resource Sharing).

Figma's Plugin Environment Isn’t a Traditional Web App

Unlike a standard web application, Figma plugins run in a sandboxed environment, which has no direct access to browser APIs like fetch from external domains. When your plugin tries to call an API that isn’t explicitly designed to support cross-origin requests, you’re likely to hit a wall—CORS errors that block your data before it even leaves the browser.

This issue is more than a technical nuisance. It slows down prototyping, complicates architecture decisions, and limits the types of integrations you can build without jumping through hoops.

Why CORS is a Dealbreaker for Plugin Developers

CORS was introduced for security—to prevent malicious scripts from interacting with resources from different origins. But in the plugin ecosystem, it becomes a massive barrier to productivity:

  • No direct access to most APIs: Even if you're building an internal tool that connects to your own company's backend, you’ll need to ensure CORS headers are correctly configured on the server.
  • You can’t use external libraries that rely on browser networking: Many third-party tools assume a standard web environment. When used inside a Figma plugin, they break silently or throw CORS-related errors.
  • Workarounds increase complexity: Proxy servers, Cloudflare Workers, or external bridge services are often required just to make a simple API call. That means extra hosting, maintenance, and security considerations.

Common Workarounds—and Their Tradeoffs

  1. Use a Proxy ServerCreate a small backend (Node, Express, etc.) that acts as a middleman. Your plugin talks to the proxy, and the proxy talks to the API.
    • ✅ Avoids CORS issues
    • ❌ Adds latency and infrastructure overhead
  2. Cloudflare Workers or Serverless FunctionsLightweight, edge-deployed functions that can fetch API data and return it to the plugin.
    • ✅ Scales well and deploys fast
    • ❌ Still needs careful auth handling and debugging can be painful
  3. Use a Design System’s Private API
  4. If you're working with a design system like Nova (or similar), exposing a plugin-specific endpoint with preflighted CORS headers can streamline requests—but it still requires dev effort on the backend.

It's Not Just CORS—Other Limitations Stack Up

  • Lack of persistent storage: LocalStorage is restricted; you must use Figma’s clientStorage API, which is async and limited.
  • No DOM access: Plugin UIs are rendered in an iframe and cannot touch the Figma canvas directly; you need to pass messages through the plugin controller.
  • Authentication flows are clunky: Since you can’t open OAuth flows naturally, you often have to open an external window, authenticate, then pass a token back manually.

Why Figma Plugin Requests Have origin: 'null'—and Why That Breaks Things

One of the more confusing issues when calling APIs from a Figma plugin is the presence of the request header:

yaml
CopyEdit
Origin: null

This happens because Figma plugins don’t run in a traditional browser tab with an assigned domain. Instead, they execute in a sandboxed environment (essentially a webview) with no origin context. As a result, any outbound fetch() or XMLHttpRequest is tagged with origin: 'null'.

While that might seem harmless, many APIs will automatically reject requests from unknown or unauthenticated origins—even if their CORS policy includes wildcards. This means even publicly available endpoints can break inside your plugin, giving you unhelpful errors like:

pgsqlCopyEditAccess to fetch at '<https://api.example.com>' from origin 'null' has been blocked by CORS policy

This restriction makes even basic integrations—like hitting a CMS API or pulling live content—feel frustratingly out of reach.

Using a CORS Proxy (With Caution)

One way developers bypass this issue is by using a CORS proxy, which receives the request from your plugin and forwards it to the destination API with correct headers. A common tool for this is:

🔗 corsproxy.io

You’d rewrite your fetch call like this:

jsCopyEditfetch("<https://corsproxy.io/?https://api.example.com/data>")

This works because the proxy is CORS-compliant and will accept origin: null—then forward the request along with appropriate headers to the actual API. It’s a useful workaround during development or for hitting APIs that you don’t control and can’t configure.

⚠️ Important Warning

Using public CORS proxies introduces serious security concerns. All your request data—including authentication tokens or user data—is routed through a third-party server. This exposes it to potential logging, misuse, or leaks.

Never use a public proxy for production traffic, especially if you're dealing with sensitive or private APIs.

Safer Alternatives for Real Products

If you're building a production-ready plugin, you'll want to avoid public proxies entirely. Safer strategies include:

  • Deploying your own proxy server (via Node, Vercel Functions, Cloudflare Workers, etc.) so you control the data path.
  • Adding CORS headers to your backend, allowing origin: null if you know it's safe (rare, but sometimes acceptable for internal tools).
  • Avoiding client-side fetches altogether—delegate API logic to a separate backend service and let the plugin communicate securely with that.

Should Figma Offer Better API Support?

In a way, the limited environment is what keeps Figma secure and performant. But as plugins grow more sophisticated—handling design tokens, AI-assisted layout, and integrations with version control—these limitations begin to feel like handcuffs.

A few things the Figma team could consider:

  • Exposing a server-side proxy service for plugins
  • Enabling opt-in CORS passthrough with vetted domains
  • Offering richer plugin permissions and a scoped OAuth flow

Conclusion

Building for Figma can feel like developing inside a locked room with only a few narrow windows. While the plugin API is well-documented and capable in many respects, the restrictions around networking and storage often leave developers feeling boxed in.

If you’re planning to build a Figma plugin that talks to external APIs, prepare yourself for CORS workarounds, proxy servers, and possibly a few late-night debugging sessions. It’s doable—but it’s far from plug-and-play.