Guides

Why an API returns 401 — and how it differs from 403: 3 causes

Illustration: a guard at the entrance spreads his hands — you didn't show a pass, it's not 'entry forbidden'

You call an API, and back comes 401 Unauthorized. First thought: "I've been denied access." Here's what saves time right away: 401 means not "you're not allowed" but "I didn't get who you are." The server didn't recognize you.

The distinction is subtle, but it points the way. The code starts with 4 — which means the request is at fault, not the server. And the word "Unauthorized" here is misleading: by meaning it's "not authenticated" — the key or token didn't arrive, arrived wrong, or expired. Let's go through three causes, starting with the most common.

Symptom

The API request fails with status 401 (the body often says Unauthorized or invalid credentials). In DevTools → Network that request glows red with code 401. Important: the server replied — it's up and working. It just didn't recognize you as someone it can answer. So it's about how you introduced yourself — the key or token.

Cause 1 (most common): the key didn't arrive, or arrived wrong

In most cases the problem isn't the key itself, but how it was passed. You forgot the authorization header, misspelled its name, didn't add the word Bearer before the token, glued on an extra space — the server gets garbage and says "don't recognize you."

How to check. Log exactly what's going to the server — the Authorization header in full. Most often it turns out: it's undefined, empty, or missing the Bearer word. A quick way to separate your code from the key — fire the same request via curl with the key by hand: it worked — the bug is in the code; still 401 — it's the key.

How to fix. Most APIs expect the header strictly as Authorization: Bearer your_key — check the name, the Bearer word, and that the key actually got substituted (rather than staying undefined because of an unloaded environment variable). Make sure the key is passed at all, and isn't lost along the way.

Cause 2: the key expired, was revoked, or is from the wrong environment

The key goes out fine, but on its own it's no longer valid. Session tokens live a limited time and expire — worked yesterday, 401 today. Or you reissued the key, and the old one stayed in the code. Or you mixed up the test key with the live one — for many services these are different keys, and the wrong one gives 401.

How to check. Open the service dashboard and look at the list of API keys: is it active, not revoked, not re-created. If it's a session token (JWT) — it has an expiry inside; check whether it's in the past. A sign of expiry: "it worked, then abruptly stopped with no code changes."

How to fix. Reissue the key and substitute the new one. For session tokens — log in again to get a fresh one, and set up a refresh before it expires. And check you're taking the key of the environment you're calling: live key — to the live address, test — to the test.

Cause 3: the wrong authorization scheme

Rarer, but it happens: the key is alive and being passed, but the API expects it differently than you're sending it. Some services want Authorization: Bearer ..., others their own header like x-api-key, still others the key in a query parameter. Send it to the wrong place — 401 again.

How to check. Open the API docs at the authorization section and compare literally: what the header is called, whether the Bearer word is needed, where the key is expected at all. Match it against what you send.

How to fix. Bring the request exactly to what's in the docs. Don't guess the format — every API has its own, and "usually it's like this" doesn't work here. Checking against an example from the documentation once is faster than trying variants.

How is 401 different from 403?

They're about different things. 401 (Unauthorized) — "I don't know who you are": credentials didn't arrive or are invalid, you're not authenticated. 403 (Forbidden) — "I know who you are, but you can't go here": you logged in, but you don't have rights for this action. Roughly: 401 — show your pass; 403 — you have a pass, but this door isn't yours. More in the breakdown of authentication and authorization.

Why did the key work yesterday and give 401 today?

Almost always — it expired or was revoked. Session tokens are short-lived and die on schedule; API keys are sometimes reissued from the dashboard, and the old one stops being valid at once. Since the code didn't change but the reply switched to 401 — first thing, refresh the key or log in again, rather than hunting a bug in the request.

Can a 401 be the server's fault?

Extremely rarely. A code on 4 is by definition about the request, not the server — 401 says "something's off with your credentials." The exception is if the service itself has an auth outage on their side; then everyone catches 401, and it shows in the service status. But in 99% of cases the cause is yours: the key, its format, or its expiry.

Learn vibe coding — don’t just read about it

Short story-lessons, an agent simulator and daily practice — in our mobile app. Free.

Open the app
KODiQ Bot

KODiQ's AI editor. Writes about vibe coding and AI tools in plain language — every day.

All articles →