GuidesAI APIS

Free AI and LLM APIs you can call from the browser

We sent a CORS preflight and a real request with a fake key to 14 hosted AI APIs from Chromium and Firefox on 26 October 2026: 9 answer fetch() directly, Anthropic needs one opt-in header, OpenAI and Cerebras block their error responses, Cloudflare Workers AI has no CORS, and GitHub Models has shut down. Free tiers come from Gemini, Groq, OpenRouter, Mistral and Cohere. A key in frontend code is readable by every visitor, so call these directly only with the user's own key or in a local prototype.

Results by provider

From a page on http://127.0.0.1 in Chromium 156 and Firefox 157, plus curl, we sent each chat endpoint a CORS preflight (OPTIONS asking for POST with its auth header and content-type), then a real POST with a fake key. If the browser can read the 401 or 400 that comes back, CORS works for that API.

AI APIs called with fetch() from a browser page, checked October 2026
ProviderBrowser CORSFree tierKey header
Google GeminiYesFlash models free, limits per project in AI Studiox-goog-api-key or ?key=
GroqYesgpt-oss-120b: 30 per minute, 1,000 per dayAuthorization: Bearer
OpenRouterYes17 free models: 20 per minute, 50 per dayAuthorization: Bearer
MistralYesFree mode, no credit cardAuthorization: Bearer
CohereYesTrial key: 1,000 calls a monthAuthorization: Bearer
DeepSeekYesNone, prepaidAuthorization: Bearer
Hugging Face routerYesNone for free accountsAuthorization: Bearer
TogetherYesNone, $15 first purchaseAuthorization: Bearer
xAIYesNone, prepaidAuthorization: Bearer
AnthropicOnly with the opt-in headerNonex-api-key
OpenAIPreflight yes, wrong-key errors blockedFree tier in allowed countriesAuthorization: Bearer
CerebrasPreflight yes, wrong-key errors blocked$5 trial credit for 30 daysAuthorization: Bearer
Cloudflare Workers AINo, OPTIONS returns 40510,000 Neurons per dayAuthorization: Bearer
GitHub ModelsRetired on 30 July 2026Service shut downNo longer accepted
Ollamalocalhost origins by defaultFree, runs on your machineNone
Chrome Prompt APINo request at allFree, on deviceNone

Gemini takes the key as an x-goog-api-key header or as ?key= in the URL, and both pass CORS. Its OpenAI-compatible endpoint, /v1beta/openai/chat/completions, allows the Authorization header too.

The Cloudflare Workers AI REST API has no CORS at all: OPTIONS returns 405 "OPTIONS not supported for requested URI". Its token is an account secret anyway, so call Workers AI from a Worker. GitHub Models is gone: GitHub retired it on 30 July 2026, inference API included, and models.github.ai now answers "OK" to every request, without CORS headers.

Free tiers

  • Gemini: Gemini 3.8 Flash (gemini-3.8-flash) is "Free of charge" on the free tier, which needs only a Google project, no billing account. Free tier prompts are used to improve Google products; paid ones are not. Gemini 4 Argon is paid only. Your limits are shown in Google AI Studio, count per project rather than per key, and the daily quota resets at midnight Pacific time.
  • Groq: the free plan runs openai/gpt-oss-120b and openai/gpt-oss-20b at 30 requests per minute, 1,000 per day, 8,000 tokens per minute and 200,000 tokens per day.
  • OpenRouter: 17 of its 467 models had ids ending in :free on the test day. Free models allow 20 requests per minute and 50 per day, or 1,000 per day once you have bought at least 10 credits.
  • Mistral: "Free mode" API access with no credit card. The limits are only shown in its console.
  • Cohere: free trial keys with 1,000 API calls a month and 20 chat requests per minute.
  • OpenAI: a Free usage tier for users in allowed countries; the next tier starts after a $5 credit purchase.

Anthropic, DeepSeek, xAI and Together list no free tier; Together's first purchase is at least $15. Hugging Face gives free accounts no Inference Providers credits, and Cerebras gives a $5 trial credit that expires after 30 days.

Your key is visible to every visitor

Anything your frontend sends, a visitor can read in DevTools. Put your own API key in a React app and anyone can copy it and spend your quota or your money. A CORS proxy does not change that. The 9 APIs that send CORS headers need no proxy, and cors.dev never stores or injects secrets: its free tier refuses Authorization headers and keys in the URL, and cors.dev Pro ($5 a month) can forward an Authorization header the browser sends, which means the key is still in the browser.

So a production app with your key needs a backend or serverless function that holds it. Direct browser calls fit two cases: local prototypes, and bring-your-own-key tools where each user pastes their own key and it stays in localStorage on their device.

Gemini from the browser with the user's own key
const apiKey = localStorage.getItem('geminiKey') ?? prompt('Paste your Gemini API key');
localStorage.setItem('geminiKey', apiKey);

const model = 'gemini-3.8-flash';
const response = await fetch(
  `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent`,
  {
    method: 'POST',
    headers: { 'x-goog-api-key': apiKey, 'Content-Type': 'application/json' },
    body: JSON.stringify({ contents: [{ parts: [{ text: 'Explain CORS in one sentence.' }] }] }),
  },
);
const data = await response.json();
if (response.status === 400) localStorage.removeItem('geminiKey');
if (!response.ok) throw new Error(data.error?.message ?? `HTTP ${response.status}`);

console.log(data.candidates[0].content.parts[0].text);

Anthropic and OpenAI in the browser

Anthropic only allows browser calls that send anthropic-dangerous-direct-browser-access: true. Without that header the preflight returns 400 "Disallowed CORS origin" and fetch() fails; with it, the preflight passes and a 401 is readable. Anthropic's TypeScript SDK sends the header when you set dangerouslyAllowBrowser: true, and OpenAI's Node SDK uses the same flag, with a README warning that it exposes your secret key.

OpenAI passes the preflight, but a chat completion or /v1/responses call with a wrong key returned 401 without an Access-Control-Allow-Origin header. The browser cannot read that response, so a typo in the key shows up as TypeError: Failed to fetch in Chromium and "NetworkError when attempting to fetch resource" in Firefox instead of OpenAI's error message. Cerebras behaves the same way. Without paid keys we could not test a successful call on either.

Claude from the browser with the opt-in CORS header
const apiKey = prompt('Paste your Anthropic API key');

const response = await fetch('https://api.anthropic.com/v1/messages', {
  method: 'POST',
  headers: {
    'x-api-key': apiKey,
    'anthropic-version': '2026-10-21',
    'anthropic-dangerous-direct-browser-access': 'true',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: 'claude-haiku-5-5',
    max_tokens: 200,
    messages: [{ role: 'user', content: 'Explain CORS in one sentence.' }],
  }),
});
const data = await response.json();
if (!response.ok) throw new Error(data.error?.message ?? `HTTP ${response.status}`);

console.log(data.content[0].text);

OpenRouter free models

OpenRouter's model list at https://openrouter.ai/api/v1/models needs no key and sends CORS headers, so a page can find the free models itself. The model id openrouter/free picks a free model for you.

OpenRouter: list the free models, then call the free router
const { data: models } = await fetch('https://openrouter.ai/api/v1/models').then((response) => response.json());
const freeModels = models.filter((model) => model.id.endsWith(':free')).map((model) => model.id);
console.log(`${freeModels.length} free models`, freeModels.slice(0, 5));

const apiKey = prompt('Paste your OpenRouter API key');
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
  method: 'POST',
  headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    model: 'openrouter/free',
    messages: [{ role: 'user', content: 'Explain CORS in one sentence.' }],
  }),
});
const data = await response.json();
if (!response.ok) throw new Error(data.error?.message ?? `HTTP ${response.status}`);

console.log(data.model, data.choices[0].message.content);

Local models: Ollama and Chrome's Prompt API

Ollama listens on 127.0.0.1:11434 and by default accepts browser requests from localhost, 127.0.0.1 and 0.0.0.0 on any port, over http or https, so a Vite dev server on http://localhost:5173 can call it directly. It also allows app://, file://, tauri:// and VS Code webviews. Any other origin needs the OLLAMA_ORIGINS environment variable, for example OLLAMA_ORIGINS=https://myapp.example.com. For other localhost problems, see CORS errors on localhost.

Chrome's built-in Prompt API runs Gemini Nano on the device through a LanguageModel global: LanguageModel.availability(), LanguageModel.create(), then session.prompt(). It is on the web since Chrome 148 and in extensions since Chrome 138, with no key and no network call after the model download; Google says no data is sent to Google or any third party. It is desktop only (Windows 10 or 11, macOS 13+, Linux, Chromebook Plus) and needs 22 GB of free disk space plus a GPU with more than 4 GB of VRAM, or 16 GB of RAM and 4 CPU cores.

Good questions.

Which LLM APIs can I call directly from browser JavaScript?

Gemini, Groq, OpenRouter, Mistral, Cohere, DeepSeek, the Hugging Face router, Together and xAI all worked from browser fetch() with no extra setup. Anthropic works once you add the anthropic-dangerous-direct-browser-access: true header.

Is there a free AI API with no credit card?

Yes. Mistral's Free mode needs no credit card, Gemini's free tier needs no billing account, and OpenRouter's :free models give 50 requests a day without buying credits. Groq's free plan and Cohere's trial keys are free as well.

Is the Gemini API free?

Yes, for Flash models: Gemini 3.8 Flash costs nothing on the free tier, while Gemini 4 Argon is paid only. On the free tier Google uses your prompts to improve its products.

Why does the OpenAI API give "Failed to fetch" in the browser?

With a wrong key, OpenAI's chat endpoint answers 401 without an Access-Control-Allow-Origin header, so the browser hides the response and fetch() throws TypeError: Failed to fetch. Check the key first; the preflight itself passes.

Is it safe to put an OpenAI or Gemini key in frontend code?

Not your own key: every visitor can read it in DevTools and use it. It is fine in a local prototype or when each user brings their own key; otherwise keep the key in a serverless function.

Can a CORS proxy hide my API key?

No. If the browser sends the key to a proxy, the key is still in the browser. cors.dev's free tier refuses keys outright, and Pro forwards an Authorization header without making it secret.