---
title: 401 Unauthorized
description: What HTTP 401 means, how it differs from 403, why tokens silently expire, and how to catch broken auth before your users do.
canonical: https://watchfor.io/docs/reference/http-status-codes/401
---

# 401 Unauthorized

What HTTP 401 means, how it differs from 403, why tokens silently expire, and how to catch broken auth before your users do.

**401 Unauthorized** means the request lacks valid authentication credentials —
none were sent, or the ones sent were rejected. The name is a historical
misnomer: it's really "unauthenticated". A correct 401 response includes a
`WWW-Authenticate` header describing how to authenticate.

## 401 vs 403

- **401** — "I don't know who you are." No credentials, expired token, bad
  signature. Retrying with valid credentials can succeed.
- **[403](/docs/reference/http-status-codes/403)** — "I know exactly who you
  are, and you're not allowed." Valid credentials, insufficient permissions.

APIs that return 403 for missing tokens (or 401 for permission failures) cause
endless client-side confusion — if you're designing one, keep the distinction
clean.

## Common causes

- **Expired tokens** — JWTs and OAuth access tokens have lifetimes; a client
  that doesn't refresh gets 401s that "come out of nowhere" exactly N minutes
  after login.
- **Rotated API keys** — someone rotates a key in the provider dashboard and
  one forgotten consumer keeps using the old one.
- **Clock skew** — JWT `exp`/`nbf` validation fails when the verifying
  server's clock drifts; tokens appear expired the moment they're issued.
- **Missing the `Authorization` header** — proxies and serverless platforms
  sometimes strip it (a classic with `Authorization` behind some CDN configs).
- **Wrong auth scheme** — sending `Bearer` where the API expects `Basic`, or
  base64-encoding Basic credentials incorrectly.
- **Cookie SameSite/domain issues** — browser sends no session cookie
  cross-site, the API sees an anonymous request.

## Debugging

Reproduce with the free [API tester](/api-tester) using the exact header —
if it works there but not from your app, the header isn't arriving as sent.
Decode JWTs (the payload is just base64 JSON) and check `exp` against the
server time.

Auth breakage is a monitoring blind spot: the public homepage stays green while
every authenticated call fails. An [API monitor](/docs/monitors/api) with a
real token exercises the authenticated path — and alerts on the 401 before
the support tickets arrive.

---

Canonical page: https://watchfor.io/docs/reference/http-status-codes/401 · All docs: https://watchfor.io/docs · Site guide: https://watchfor.io/llms.txt
