Fixing CORS issues when accessing Notion API from client-side React application

I’m working on a React project that runs entirely in the browser without a backend server. The app needs to fetch data from Notion’s API directly from the frontend code, but I keep running into CORS problems every time I try to make the requests.

I’ve tried setting different headers and request configurations, but nothing seems to work. The browser keeps blocking my API calls with cross-origin errors. Does anyone know the proper way to configure the fetch requests or if there are specific headers that need to be included to make this work?

Here’s a basic example of what I’m trying to do:

const fetchNotionData = async () => {
  try {
    const response = await fetch('https://api.notion.com/v1/databases/my-db-id', {
      method: 'GET',
      headers: {
        'Authorization': 'Bearer my-token',
        'Notion-Version': '2022-06-28'
      }
    });
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('CORS error:', error);
  }
};

Any suggestions on how to resolve this?

cors-anywhere is pretty unreliable these days. Just set up a simple backend instead - I threw together a basic Node.js server on Heroku’s free tier to proxy Notion requests. Took about 30 minutes when I hit the same problem.

Nope, you can’t get around CORS when hitting Notion’s API directly from React. Notion doesn’t send the CORS headers browsers need, so your requests get blocked. They do this on purpose - they don’t want API keys sitting in client-side code where anyone can grab them from your source. You’ll need a backend proxy or serverless function to handle the API calls instead. Vercel Functions, Netlify Functions, or a basic Express server all work great for this. Your React app calls your backend endpoint, which then forwards everything to Notion’s API with the auth headers safely tucked away server-side.

Had this exact problem last month. Your fetch setup is fine - Notion blocks browser requests on purpose for security. If you call their API directly from React, your token gets exposed in the client code where anyone can grab it from dev tools. I fixed it with a Next.js API route. Your React app hits your serverless function instead, which adds the auth headers server-side and calls Notion for you. Keeps the token hidden and kills the CORS issue. Not using Next.js? AWS Lambda or Cloudflare Workers do the same thing with barely any setup.