CORS proxy for Webflow, Framer, and Bubble custom code
A page builder gives you no server to put a proxy on. This post covers which parts of Webflow, Framer, and Bubble run into CORS at all, and how to route those calls through a hosted proxy without leaving the platform.
First: figure out if you actually have a CORS problem
CORS is enforced by the browser, on JavaScript running in the browser. Not every feature in these tools runs client-side, so not everything hits it:
- Webflow: a
<script>in custom code or an Embed element callingfetch()runs in the visitor's browser. CORS applies. - Framer: a code component or code override that calls an API runs in the browser. CORS applies.
- Bubble: the built-in API Connector calls most APIs from Bubble's own server, not the visitor's browser, so CORS does not apply there. Client-side JavaScript does: a "Run Javascript" workflow action, or a plugin that executes in the browser.
If the console says "blocked by CORS policy," you're in the client-side case. If a call fails with no CORS message in the console, the problem is something else, so check the actual response first.
The fix: one fetch through the proxy
Wrap the target URL and send it to the proxy with your key. The same snippet works on all three platforms:
const target = encodeURIComponent('https://api.example.com/data');
fetch(`https://api.corsproxy.dev/proxy?url=${target}&key=YOUR_CORSPROXY_KEY`)
.then(r => r.json())
.then(data => {
// use data here: update an element, a React state, or a Bubble state
});
Where to put it:
- Webflow: inside a
<script>tag in Page Settings → Custom Code, or in an Embed element on the page. Check that your site plan supports custom code before you build on it. - Framer: in a code component, call it inside a
useEffectand store the result withuseState; in a code override, run it from the override and pass the value as a prop. - Bubble: in a "Run Javascript" action or your plugin's client-side code, then write the result into a custom state or element. Calls made through the standard API Connector don't need this; they already run on Bubble's server.
Don't put third-party API keys in the browser
No-code custom code is visible in page source, so never hardcode a third-party secret (an OpenAI key, a private API token) into a Webflow or Framer embed. Use managed upstream headers instead: store the credential once on your corsproxy.dev API key, and the browser only sees your corsproxy.dev key.
That key is still public, so lock it down:
- Set
allowed_originsto your site. This only stops other websites using the key in a browser; a script outside a browser can send anyOriginheader. On the Free plan, keys also always accepthttp://localhost:*andhttp://127.0.0.1:*. - Set
allowed_targetsto the API host you call, so a copied key can't proxy to anything else on your quota.
Try it
Create a free key and paste it into the snippet above.