# Yahoo Finance API 401 unauthorized crumb error

## TL;DR
Yahoo's 401 with a crumb complaint means your request missed the cookie-plus-crumb handshake Yahoo requires on its quote endpoints, and the unofficial endpoints this affects can change or break without notice. The durable fix is Yahoo's official API or a licensed market data provider rather than reverse-engineered endpoints. If you must use the web endpoints, fetch a fresh crumb with its cookies per session and stop when Yahoo changes the handshake instead of chasing it.

## The error
```text
HTTP 401 Unauthorized
{"finance":{"error":{"code":"Unauthorized","description":"Invalid Crumb"}}}
```

## When this helps
- Yahoo quote fetches fail with invalid-crumb 401s
- a market data agent breaks after Yahoo changes its web endpoints
- deciding between Yahoo's web endpoints and official market data APIs
- chart or quote intake needs a stable source

## When it doesn't
- you want to hammer the unofficial endpoints at scale; they are not built for that
- you need redistribution rights; unofficial endpoints grant none
- the handshake changed again; that is Yahoo telling unofficial users to move on

## Works with
Unofficial web endpoints change without notice; the official Yahoo Finance API is versioned. python 3.8+ with requests, curl 7.x+.

## Steps
### 1. Reproduce the crumb failure to confirm the diagnosis
```bash
curl -s "https://query1.finance.yahoo.com/v8/finance/chart/AAPL" -o crumb_test.json -w "HTTP %{http_code}\n"
head -c 200 crumb_test.json; echo
```
Expected: HTTP 401 with an invalid-crumb message. A 429 instead means you are rate-limited on top of the auth problem.

### 2. Do the cookie plus crumb handshake in one session
```python
import requests
s = requests.Session()
s.headers.update({"User-Agent": "IntelBriefingBot/1.0"})
r = s.get("https://fc.yahoo.com", timeout=20)
crumb = s.get("https://query1.finance.yahoo.com/v1/test/getcrumb", timeout=20).text
q = s.get("https://query1.finance.yahoo.com/v8/finance/chart/AAPL?crumb=" + crumb, timeout=20)
print("chart status:", q.status_code)
```
Expected: HTTP 200 on the chart request when the handshake is fresh. Crumbs expire, so redo the handshake per session, not per process lifetime.

### 3. Rate-limit the unofficial endpoints gently
```python
import time
print("one symbol per 2 seconds, cache chart JSON by symbol and date")
print("back off on any 429 or 401; a changed handshake is a stop signal, not a bug")
```
Expected: A sustainable polling pattern. These endpoints are not a public API, so polite use is what keeps them working at all.

### 4. Move production intake to the official API or a licensed provider
```bash
curl -s "https://api.yahoofinance.com/v1/quotes?symbols=AAPL" -H "your auth header finance api key]" -o official.json -w "HTTP %{http_code}\n"
```
Expected: HTTP 200 from the official API. Reverse-engineered endpoints break without notice; the official API and licensed providers are the durable intake.

## Other ways people phrase this
### yahoo finance invalid crumb 401
The handshake half. Fresh cookies plus a fresh crumb per session is the whole trick, while it lasts.

### yahoo finance api unauthorized quote download
Often the same crumb problem on the download endpoint. The official API is the stable answer.

### query1.finance.yahoo.com 401
The endpoint most scrapers hit. It is unofficial and unsupported; plan the migration.

## Why it happens
Yahoo guards its web quote endpoints with a cookie-plus-crumb handshake that ties requests to a session. The crumb expires and the handshake changes periodically, which breaks hardcoded integrations. Yahoo offers these endpoints for its own site, not as a public API, so breakage is expected and the official API is the intended path.

## Edge cases
- Crumbs are single-session; sharing one crumb across workers triggers 401s.
- Aggressive polling of unofficial endpoints earns IP blocks that also break the handshake flow.
- Historical chart data barely changes; cache it by symbol and date range instead of re-pulling.
- If the business depends on the data, budget for a licensed provider; free unofficial access is not a foundation.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_CookbO5u7fTKLTr-Akr6kA
