CORS requirements for Framer plugins
Framer plugins run on Framer-managed domains. When a plugin talks to an external API, that API must explicitly allow requests from those domains. Missing or incomplete CORS configuration is one of the most common reasons plugin submissions fail review.
This guide explains exactly which domains to allow and how to handle them safely.
Why CORS matters for plugins
Framer plugins run in the browser. Any request from a plugin to a backend API is subject to the browser’s CORS rules.
If the API does not allow the plugin’s origin, the browser blocks the request before it ever reaches the server. This usually shows up as a generic CORS error in the console, even though the backend itself is working correctly.
Plugin domain formats
Every Framer plugin is served from one of two domain patterns. Both must be allowed.
Production domain
idis a stable identifier for the plugin.This domain is used by all end users once the plugin is approved.
This domain never includes a version ID.
Version-specific domain
versionIdis unique for each submitted version.This domain is used during plugin review and testing.
Only the plugin creator and the marketplace reviewer ever load this domain.
When a new version is approved, users are automatically switched to the production domain. If CORS is only configured for the version-specific domain, the approved plugin will break for users.
Common CORS mistakes
Allowing only one domain
Many APIs whitelist just one origin, usually the production domain. During review, the plugin runs on the version-specific domain and fails with a CORS error.
Allowing a single version ID
Some implementations hardcode a specific [id]-[versionId] origin. This works once, then breaks on the next submission because the version ID changes.
Using * with credentials
Using Access-Control-Allow-Origin: * does not work if the plugin sends cookies or authorization headers. Browsers block this combination.
Recommended approach
The safest approach is to dynamically allow any origin that matches your plugin ID, and supports all Framer’s plugin domain patterns.
This avoids manual updates and works for all future versions without changes.
Example: dynamic CORS headers in JavaScript
The function below inspects the Origin header and returns the correct CORS headers if the request comes from a valid Framer plugin domain.
This pattern works in Node.js, Bun, or a Cloudflare Worker.
Handling preflight requests
For OPTIONS requests, return the same headers with a 204 or 200 response.
What to double-check before submitting
Before submitting a plugin for review, confirm the following:
Both domain patterns are allowed.
No version IDs are hardcoded.
Preflight requests return the correct headers.
Credentials are only enabled if they are actually required.
Getting CORS right once prevents review delays and avoids production-only failures after approval.