GuidesNEWSAPI
NewsAPI CORS error in production
NewsAPI's free Developer plan allows browser requests only from localhost, so a fetch that worked in development fails once your site is deployed, with the code corsNotAllowed. On 28 October 2026 CORS for all origins started at the Business plan, $449 a month, and the terms limited the Developer plan to development environments. A CORS proxy can make the browser error go away, but it does not change NewsAPI's plan terms. The $0 route is publishers' RSS feeds through the free https://proxy.cors.dev/ tier: no signup, GET and HEAD, about 600 requests a minute per IP.
What the NewsAPI error means
Developers whose sites broke after deploying to hosts such as Netlify or Firebase report this response from newsapi.org:
{"status":"error","code":"corsNotAllowed","message":"Requests from the browser are not allowed on the Developer plan, except from localhost."}
A Stack Overflow question about a Netlify site reports it with HTTP status 426 (Upgrade Required). The code is not on NewsAPI's errors page, which lists apiKeyDisabled, apiKeyExhausted, apiKeyInvalid, apiKeyMissing, parameterInvalid, parametersMissing, rateLimited, sourcesTooMany, sourceDoesNotExist and unexpectedError. We had no valid key on 28 October 2026, so we could not reproduce it ourselves.
What we could test: GET https://newsapi.org/v2/top-headlines?country=us&apiKey=x returned 401 apiKeyInvalid with no Access-Control-Allow-Origin, for an Origin of https://example.com and of http://localhost:3000. The OPTIONS preflight answered 200 with Access-Control-Allow-Origin: *. So the preflight passes, the error response has no CORS header, and the console shows a generic CORS error; the real code is only visible in the Network tab.
Why it works on localhost and fails when deployed
Nothing is wrong with your fetch code or your host. NewsAPI decides by plan, as its pricing page and terms showed on 28 October 2026:
- Developer ($0): development and testing only, 100 requests a day with no extra requests, articles with a 24 hour delay, search up to a month back, and "CORS enabled for localhost", whose tooltip reads "Requests can be made via the browser only while testing from localhost."
- Terms: the Developer plan "may be used for development and testing in a development environment only, and cannot be used in a staging or production environment (including internally)".
- Business ($449 a month): 250,000 requests, $0.0018 per extra request, new articles in real time, search up to 5 years back, and "CORS enabled for all origins": "Requests can be made via the browser from all domains in production."
- Advanced ($1,749 a month): 2,000,000 requests, $0.0009 per extra request, 99.95% uptime SLA. Enterprise is custom.
What a CORS proxy changes, and what it does not
A CORS proxy fetches the response for you and adds Access-Control-Allow-Origin, so the browser stops blocking it. Through https://proxy.cors.dev/ our invalid-key 401 came back with CORS headers and was readable. The free tier forwards apiKey in the query string but refuses an X-Api-Key header with 400 header_not_allowed; cors.dev Pro forwards Authorization and custom headers you configure, such as X-Api-Key.
We do not know whether NewsAPI would accept a proxied Developer-plan request with a valid key, and for the licence it does not matter. A proxy does not change:
- The terms: the Developer plan is for development only, so a live site breaks them whether the request comes from a browser, a proxy or your own server. cors.dev Pro does not change that either.
- The quota: 100 requests a day, shared by every visitor, for articles that are 24 hours old.
- The key: a key in page code or in the URL is visible to anyone who opens DevTools. cors.dev does not hide keys.
Your options
- Develop on localhost
keep the free key for building and testing, as the plan intends.
- Pay for Business and call it from the browser
$449 a month buys CORS for all origins, with the key visible in your page.
- Pay for Business and call it from a backend
a server or serverless function on a paid plan keeps the key private and meets the production terms.
- Switch to free feeds
publishers' RSS feeds need no key and no plan, and work through cors.dev.
| Option | Monthly cost | Works in production | Key visible to visitors | Article delay |
|---|---|---|---|---|
| Developer plan on localhost | $0 | No, development only | Yes, in page code | 24 hours |
| CORS proxy with the Developer plan | $0 | No, breaks the terms | Yes, in the URL | 24 hours |
| Business plan from the browser | $449 | Yes | Yes, in page code | Real time |
| Business plan from your backend | $449 plus hosting | Yes | No | Real time |
| Free RSS feeds through cors.dev | $0 | Yes, check each feed's terms | No key | Live feed |
Replace NewsAPI with free feeds through cors.dev
For a portfolio project or a personal dashboard that cannot justify $449 a month, read publishers' RSS feeds instead. BBC News (https://feeds.bbci.co.uk/news/rss.xml) and Al Jazeera (https://www.aljazeera.com/xml/rss/all.xml) need no key but send no CORS headers. Through cors.dev both returned 200 on 28 October 2026, 57 articles together.
This function maps RSS items to NewsAPI's article shape (source.name, title, description, url, publishedAt), so the code that renders your NewsAPI results keeps working:
// Runs in a module script or the DevTools console
const proxy = 'https://proxy.cors.dev/';
// Returns RSS items in NewsAPI's article shape, so existing rendering code keeps working
async function rssArticles(feedUrl, sourceName) {
const response = await fetch(proxy + feedUrl);
if (!response.ok) throw new Error(`${sourceName} failed: ${response.headers.get('X-Cors-Error') ?? response.status}`);
const xml = new DOMParser().parseFromString(await response.text(), 'text/xml');
const text = (item, tag) => item.getElementsByTagName(tag)[0]?.textContent.trim() ?? '';
return [...xml.getElementsByTagName('item')].map((item) => ({
source: { id: null, name: sourceName },
title: text(item, 'title'),
description: text(item, 'description'),
url: text(item, 'link'),
publishedAt: new Date(text(item, 'pubDate')).toISOString(),
}));
}
const feeds = await Promise.all([
rssArticles('https://feeds.bbci.co.uk/news/rss.xml', 'BBC News'),
rssArticles('https://www.aljazeera.com/xml/rss/all.xml', 'Al Jazeera'),
]);
const articles = feeds.flat().sort((a, b) => b.publishedAt.localeCompare(a.publishedAt));
console.table(articles.slice(0, 10));The free tier needs no signup: prefix the URL with https://proxy.cors.dev/. It allows GET and HEAD, about 600 requests a minute per IP, no daily quota and responses up to 6 MiB, with no caching. More feeds, with sizes and item counts, are in free news APIs without a key.
Good questions.
Why does the console show a CORS error instead of the NewsAPI message?
On the error we could test, a 401, NewsAPI sent no Access-Control-Allow-Origin header, so the browser hides the response body from your code and logs a CORS error. Click the failed request in the Network tab to read the JSON and its code.
Does NewsAPI work from the browser on the free plan?
Only from localhost. The Developer plan's pricing entry says "Requests can be made via the browser only while testing from localhost.", and its terms rule out staging and production. CORS for all origins starts with the Business plan at $449 a month.
Will a serverless function fix the NewsAPI error for free?
It removes the browser CORS check and keeps the key off the page. It does not change the terms: the Developer plan cannot be used in staging or production, so a live site on a backend still needs a paid plan, from $449 a month.
Does a CORS proxy hide my NewsAPI key?
No. A key in the URL, or in a header the browser sends, is visible to anyone who opens the Network tab, and cors.dev does not hide it. Keep a key that must stay secret on your own backend.
Why do I get 400 header_not_allowed when I send X-Api-Key through cors.dev?
The free tier refuses credential headers such as X-Api-Key and Authorization, and forwards only query-string keys such as apiKey. cors.dev Pro, $5 a month for 500,000 requests with a 7-day trial of 1,000 requests and no card, forwards Authorization and custom headers you configure, such as X-Api-Key, but it does not make a Developer-plan key valid in production.
How much does NewsAPI cost for a production website?
On 28 October 2026 the Business plan was $449 a month for 250,000 requests and $0.0018 per extra request, and Advanced was $1,749 a month for 2,000,000 requests. Enterprise is custom; the free Developer plan is for development only.