UnblockDevs

Why Is My API Request Failing? Fix HTTP Header Issues (Auth, CORS, Content-Type)

API calls are failing with no useful error message — just a 401, a 403, or a vague CORS block. In 90% of cases, the root cause is a missing or wrong HTTP header. Here are the 5 most common header-related API failures and exactly how to fix each one, with real code examples for JavaScript fetch, Axios, and cURL.

The most common API errors caused by wrong headers

401 Unauthorized — Missing or invalid Authorization header
403 Forbidden — Correct token but wrong scope or format
415 Unsupported Media Type — Missing Content-Type header
CORS blocked — Server missing Access-Control-Allow-Origin
400 Bad Request — Body sent without Content-Type declaration
1

Fix: Missing Authorization Header

A 401 Unauthorized response almost always means the server did not receive a valid Authorization header. The header must be spelled exactly right and the value format must match what the API expects — most modern APIs use Bearer token format.

Authorization header — wrong vs correct

Missing auth

❌ Bad
// Missing Authorization header entirely
fetch('https://api.example.com/users', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    // No Authorization header — will get 401
  }
})

Correct auth

✅ Good
// Correct: Bearer token in Authorization header
fetch('https://api.example.com/users', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer eyJhbGciOiJSUzI1NiJ9...',
  }
})
javascriptAuthorization header — fetch, Axios, and cURL
// JavaScript fetch
const response = await fetch('https://api.example.com/users', {
  headers: {
    'Authorization': 'Bearer ' + token,
    'Content-Type': 'application/json',
  },
});

// Axios — set globally for all requests
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;

// Axios — per-request
const response = await axios.get('https://api.example.com/users', {
  headers: { 'Authorization': 'Bearer ' + token },
});

// cURL
curl -H "Authorization: Bearer eyJhbGc..."      https://api.example.com/users

// Basic Auth (username:password base64 encoded)
curl -H "Authorization: Basic dXNlcjpwYXNz"      https://api.example.com/users
# Or shorthand: curl -u "username:password" https://api.example.com/users

Important

The header name is case-insensitive (authorization = Authorization), but the value format is case-sensitive. Use Bearer token not bearer token — some APIs will reject lowercase. Always check the API docs for the exact expected format.

2

Fix: Wrong Content-Type Header

When you send a POST or PUT request with a JSON body, the server needs to know what format the body is in. Without Content-Type: application/json, the server may reject the body entirely, return a 400 or 415 error, or silently misparse the data.

Missing Content-Type on POST request

Missing Content-Type

❌ Bad
// No Content-Type — server receives body as raw text
fetch('https://api.example.com/users', {
  method: 'POST',
  body: JSON.stringify({ name: 'Alice', email: 'alice@example.com' }),
  // Missing: 'Content-Type': 'application/json'
})

Correct Content-Type

✅ Good
// Correct: Content-Type tells server to parse body as JSON
fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + token,
  },
  body: JSON.stringify({ name: 'Alice', email: 'alice@example.com' }),
})

Note that Content-Type must match the actual body format. Common values:

httpCommon Content-Type values
# JSON body (most REST APIs)
Content-Type: application/json

# URL-encoded form data (HTML form default)
Content-Type: application/x-www-form-urlencoded

# Multipart form data (file uploads)
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary...

# Plain text
Content-Type: text/plain; charset=utf-8

# XML
Content-Type: application/xml

Axios auto-sets Content-Type for JSON

If you use axios.post(url, { name: 'Alice' }), Axios automatically sets Content-Type: application/json. But if you pass a FormData object, it sets multipart/form-data. If you manually stringify the body with JSON.stringify() inside Axios, you must also set Content-Type manually.
3

Fix: CORS Header Issues

CORS (Cross-Origin Resource Sharing) errors are some of the most frustrating API failures because they are enforced by the browser — the server may have responded successfully but the browser blocks your JavaScript from reading the response. CORS is a server-side configuration issue. You cannot fix it from the client side.

The exact CORS error message

Access to fetch at 'https://api.example.com/users' from origin 'https://yoursite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

CORS — server response missing CORS headers vs correct configuration

Missing CORS headers

❌ Bad
# Server response missing CORS headers — browser blocks the response
HTTP/2 200
content-type: application/json
# No Access-Control-Allow-Origin — browser refuses to give JS the response

Correct CORS headers

✅ Good
# Server response with correct CORS headers
HTTP/2 200
content-type: application/json
access-control-allow-origin: https://yoursite.com
access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS
access-control-allow-headers: Authorization, Content-Type
access-control-allow-credentials: true
javascriptAdd CORS headers in Express (Node.js)
const cors = require('cors');

// Allow all origins (development only — not for production)
app.use(cors());

// Allow specific origin with credentials
app.use(cors({
  origin: 'https://yoursite.com',
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Authorization', 'Content-Type'],
  credentials: true, // Required if sending cookies or Authorization header
}));

// Handle preflight for all routes
app.options('*', cors());

Test CORS issues with the UnblockDevs CORS Tester

Use the UnblockDevs CORS Tester to check which CORS headers your API is returning and whether they are configured correctly for your origin. It shows exactly which headers are missing or misconfigured.
4

How to Verify Headers Are Being Sent

Before debugging why a header is not working, confirm it is actually being sent. Headers can be silently dropped by middleware, proxies, CORS preflight handling, or framework-level configuration.

1

Open Chrome DevTools Network tab

Press F12 → Network tab. Make sure it is open before you make the request, or reload the page.

2

Find the failing request

Filter by "Fetch/XHR" for API calls. Click the request name to open its detail panel.

3

Click the Headers tab

Check the "Request Headers" section — this is what was actually sent to the server, not what you wrote in code. Middleware or the browser may have modified headers.

4

Verify the exact header name and value

Check for typos, wrong capitalization in the value, missing "Bearer " prefix, or the token being undefined (showing "Bearer undefined").

5

Check response headers for the CORS preflight

For custom headers (like Authorization), the browser sends an OPTIONS preflight request first. Find that OPTIONS request in DevTools and verify the server's Access-Control-Allow-Headers includes your custom header.

Analyze response headers in one click

Use the HTTP Headers Analyzer — paste the response headers from DevTools to get a full security and correctness audit. It flags missing CORS headers, insecure cache policies, missing Content-Type, and more.
5

Why Your Header Is Not Being Sent

You added the header in code but it is not appearing in DevTools. Here are the 6 most common reasons a header disappears before reaching the server:

CORS preflight blocking the header

Custom headers trigger a CORS preflight (OPTIONS) request. If the server does not return Access-Control-Allow-Headers including your header, the browser drops it from the actual request.

Middleware stripping the header

Server-side middleware (auth layers, API gateways, reverse proxies like Nginx) may remove headers before they reach your handler. Log headers at the first middleware to check.

Token is undefined at runtime

Your code sets "Bearer " + token but token is undefined — resulting in "Bearer undefined". Add a null check and log the token value before the request fires.

Framework-level override

Some frameworks (Next.js API routes, Express middlewares) automatically set or override certain headers. Check your middleware stack for header manipulation.

Missing Vary: Origin on cached response

If a CDN caches a response without Vary: Origin, it may serve a cached CORS-less response to a different origin. The server must include Vary: Origin for CORS headers to work through CDNs.

Header added to wrong request object

In Axios, if you set headers on the instance config but then make a request with a different instance, the headers are not inherited. Verify you are using the correct Axios instance.

Header being stripped by proxy vs correct CORS + Vary configuration

Proxy stripping headers

❌ Bad
# Nginx proxy stripping the custom header and no Vary header
location /api/ {
  proxy_pass http://backend;
  # Missing: proxy_pass_header Authorization;
  # Missing: add_header Vary Origin;
}

Correct proxy config

✅ Good
# Correct Nginx config — passes headers through + correct Vary
location /api/ {
  proxy_pass http://backend;
  proxy_pass_header Authorization;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  add_header Vary Origin always;
  add_header Access-Control-Allow-Origin $http_origin always;
  add_header Access-Control-Allow-Credentials true always;
}

Frequently Asked Questions