Calling APIs from no-code tools: Webflow, Bubble and Framer
Why API calls fail with CORS errors in no-code tools, which calls run in the browser and which on a server, and how to keep API keys out of your published site.
No-code tools make it easy to build a polished site, and sooner or later you want it to show live data: prices, availability, a feed, the result of an AI model. The first attempt often fails with a CORS error, or works but leaves an API key visible to anyone who views the source. Calling APIs from no-code tools like Webflow, Bubble and Framer is safe and reliable once you know one thing: whether a given call is made by the visitor’s browser or by a server.
This guide explains that distinction for each tool, why CORS errors appear, and how to keep keys out of your published site.
The one question: browser or server?
Every API call in a no-code site is made by one of two parties:
- The visitor’s browser. Custom code embeds, scripts and components that run in the page all make requests from the browser. The browser enforces CORS, so the API must allow your site’s origin, and anything in the request, including keys, is visible in the browser’s developer tools.
- A server. Some platforms send certain API calls from their own infrastructure. CORS does not apply there, and values configured as private never reach the visitor.
A CORS error is the browser telling you the API did not allow your origin. It is not a bug in your no-code tool, and it cannot be fixed by settings in the page. If you want to understand the error itself, what CORS is explains it in plain terms.
Webflow
Webflow sites are delivered as pages to the visitor’s browser. Custom code you add, whether in an Embed element or in page or site settings, runs in that browser.
That means:
- A
fetchin custom code to a third-party API is a cross-origin request from your published domain. If the API does not send CORS headers allowing that domain, the browser blocks the response. - Any key you put in that code is public. Visitors, crawlers and anyone curious can read it from the page source.
Practical options for Webflow:
- Use APIs that are designed for browsers, with publishable keys that are restricted to your domain.
- Route the call through a proxy that adds CORS headers and accepts a key locked to your origin.
- Keep secret keys off the page entirely, in a server-side vault or a backend you control.
Bubble
Bubble’s API Connector is the usual way to call external APIs, and it generally sends requests from Bubble’s servers rather than from the visitor’s browser. Because of that, calls made through the API Connector are not subject to CORS, and Bubble lets you mark sensitive parameters as private so they are not exposed to the client.
CORS returns as soon as a call is made from the page instead:
- JavaScript in an HTML element or a plugin’s client-side code runs in the browser.
- A plugin or setting that makes a call client-side behaves the same way.
For those, the same rules as any website apply: the API must allow your origin, and keys in that code are visible. Check each plugin’s documentation for whether it calls APIs from the browser or from a server.
Framer
Framer sites also run in the visitor’s browser. Code components and code overrides are React code executing in the page, so a fetch from them is a browser request:
// A Framer code component: runs in the visitor's browser, so CORS applies.
import { useEffect, useState } from 'react';
export default function LatestPrice() {
const [price, setPrice] = useState<string>('…');
useEffect(() => {
fetch('https://api.example.com/price/btc')
.then((response) => response.json())
.then((data) => setPrice(data.price));
}, []);
return <span>{price}</span>;
}
If the API does not allow your Framer domain, this fails with a CORS error. As with Webflow, any key written in the component is public. Built-in data features differ by tool and change over time, so check the tool’s documentation for where a particular request is sent from.
Keeping API keys out of your published site
Whatever the tool, a key inside page code is published. Minifying or obfuscating it changes nothing: the browser has to send the real value, so anyone can read it from the network panel. The full argument is in why you can’t hide an API key in frontend code.
Sort your keys into two groups:
- Publishable keys are designed to be public and are restricted by the provider, usually to specific origins or with read-only permissions. They are fine in page code. Publishable API keys explains what makes a key safe to publish.
- Secret keys grant real access: they can spend money, read private data or change settings. They must never appear in page code.
For secret keys, the call has to be completed by a server: your own backend, a server-side feature of your no-code platform, or a proxy that holds the secret for you and adds it to the outgoing request.
Calling APIs through ProxifyEdge from a no-code site
ProxifyEdge is built for the browser-side case. You send the request to its proxy endpoint with a public key; it calls the API and returns the response with CORS headers your site is allowed to read:
<script>
const target = 'https://api.example.com/price/btc';
fetch(`https://api.proxifyedge.com/proxy?url=${encodeURIComponent(target)}`, {
headers: {
'X-API-Key': 'pk_your_public_key',
// The real upstream key is stored in ProxifyEdge, not in this page.
'X-Proxify-Upstream-Authorization': 'Bearer {{secret.PRICE_API_KEY}}',
},
})
.then((response) => response.json())
.then((data) => (document.querySelector('#price').textContent = data.price));
</script>
Two things make this safe to paste into a page:
- A live ProxifyEdge key only answers the origins you list for it in the dashboard, such as your Webflow or Framer domain. Another site copying the key cannot read responses with it.
- The upstream credential lives in the secrets vault and is referenced as
{{secret.NAME}}. ProxifyEdge substitutes the real value on the way out, and only for the hosts you allow.
While building in the editor or a staging domain, either add that origin to the key or use a test key, which answers any origin. You can try requests without writing code in the playground.
Troubleshooting the usual errors
When a call fails, the browser’s developer tools tell you which case you are in. Open them, reload the page, and look at the Console and Network tabs:
- “blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header” means the API did not allow your domain. The request may have reached the API, but the browser hid the response. See how to fix the missing Access-Control-Allow-Origin header.
- A
401or403with a proper response body means CORS is fine but the API rejected your credentials. Check the key, and whether it is being sent in the header the API expects. - It works in the editor preview but not on the published site. The preview and the published site are different origins. Add the published domain, and any custom domain, to the key’s allowed origins.
- It works for you but not for visitors. A browser extension that disables CORS, or a cached response, may be hiding the problem on your machine. Test in a private window.
A quick checklist
- Find out whether the call runs in the browser or on a server.
- For browser calls, confirm the API allows your origin, or route through a proxy.
- Put only publishable, origin-restricted keys in page code.
- Keep secret keys in a server-side vault or backend.
- Add every domain you publish to, including staging, to the key’s allowed origins.
Key takeaways
- CORS errors in no-code tools come from calls made in the visitor’s browser.
- Code embeds in Webflow, code components in Framer and client-side code in Bubble all run in the browser.
- Anything in page code is public; only publishable, origin-restricted keys belong there.
- Secret keys need a server or a proxy that substitutes them server-side.