CORS for Local Development (localhost)

Handle CORS during local development when frontend and backend run on different ports. Covers proxy configuration, environment-based origins, and common localhost pitfalls.

Common Issues

Detailed Explanation

CORS and localhost

During development, your frontend typically runs on http://localhost:3000 while the API runs on http://localhost:8080. Because the port is part of the origin, these are different origins and CORS applies.

Option 1: Add localhost to Allowed Origins (Development Only)

const allowedOrigins = process.env.NODE_ENV === "production"
  ? ["https://app.example.com"]
  : ["http://localhost:3000", "http://localhost:5173", "http://127.0.0.1:3000"];

app.use(cors({ origin: allowedOrigins, credentials: true }));

Option 2: Framework Dev Proxy (No CORS Needed)

Most frontend frameworks offer a development proxy that forwards API requests through the dev server, making them same-origin.

Vite:

// vite.config.ts
export default defineConfig({
  server: {
    proxy: {
      "/api": "http://localhost:8080",
    },
  },
});

Next.js:

// next.config.js
module.exports = {
  async rewrites() {
    return [
      { source: "/api/:path*", destination: "http://localhost:8080/api/:path*" },
    ];
  },
};

Create React App:

{ "proxy": "http://localhost:8080" }

Option 3: Wildcard in Development

app.use(cors({
  origin: process.env.NODE_ENV === "production" ? "https://app.example.com" : "*",
}));

localhost vs 127.0.0.1

http://localhost:3000 and http://127.0.0.1:3000 are different origins. If your browser navigates to localhost but the API allowlist only includes 127.0.0.1, CORS will fail. Include both or use a proxy.

Common Pitfall: IPv6

On some systems, localhost resolves to ::1 (IPv6) instead of 127.0.0.1. Your backend may be listening on 127.0.0.1 only. Check with curl -v http://localhost:8080 to see which IP is used.

Use Case

A developer runs a React app on localhost:3000 and a Python Flask API on localhost:5000. They encounter CORS errors and want the simplest fix that doesn't involve changing server code — a frontend proxy.

Try It — CORS Header Builder

Open full tool