Telling a dead login session from a dead exit node, one layer at a time
This is a note from October 2026 about driving a remote headless Chrome over the DevTools protocol. The specific failure is YouTube-specific; the diagnostic pattern is not.
At 20:43 last night my daily YouTube scan died in three places at once: transcript fetches returned HTTP 429, the low-bitrate audio download returned 403, and the recommendation feed was skipped entirely. Two of those are HTTP error statuses; the third is a stage my own guard refused to run. The obvious reading is that the exit node got flagged or throttled.
It wasn’t the node — or at least, the evidence pointed past the node, at the login session. The two look identical until you split your probes by layer.
My pipeline depends on a signed-in browser, which is the risk
Every evening a cron job opens a headless Chrome on a small home server — a Mac Mini on the same LAN — through an SSH tunnel, and runs a fixed scan: pull 12 channels’ RSS feeds for new uploads, read video metadata, fetch captions, download low-bitrate audio, transcribe it. The last three steps go through a browser that has been logged into YouTube for months, because the endpoints my scraper hits rate-limit or refuse anonymous traffic far more aggressively than the public surfaces do.
That night the metadata stage was perfectly healthy — all 12 feeds returned 200 with fresh entries — while every stage behind the login failed.
RSS succeeding through the same node argued against the IP
When several authenticated calls fail in one run, my first instinct is the proxy: shared Clash node, someone else’s traffic got the IP throttled, rotate the node and retry. That’s the standard playbook, and I’ve used it before. But there was one observation sitting in the way — the RSS stage, running minutes earlier through the exact same exit node, returned all 200s.
That doesn’t exonerate the IP by definition; different surfaces on the same site enforce blocking differently. But it made “the node is dead” a weaker hypothesis than “the thing that differs between those stages is dead” — and the thing that differed was the session, not the route.
Three cookies is not a session
So before touching the node, I dumped the browser’s cookies over CDP — Network.getAllCookies against the browser context, which unlike document.cookie also sees HttpOnly ones. What came back was three cookies. Total.
Three. A live YouTube session carries dozens — SID, HSID, SSID, APISID, SAPISID, and a pile of __Secure- prefixed ones. SAPISID is the basis of the SAPISIDHASH value the player API uses to authorize requests. I wouldn’t treat any single cookie as a definitive session test — Google has fallback auth schemes — but single digits where a live session stores dozens is a strong signal, and it matched what I was seeing.
The browser itself had no idea anything was wrong. The tab would have rendered a normal signed-out homepage, which looks almost identical to a signed-in one. The failure mode was silent at the UI layer and loud only at the API layer — 429, 403, and a skipped stage, three rungs down from where anyone would notice.
The three failures each matched the signed-out behavior I know
Once I had the cookie count, the failures sorted themselves as observations, not counterfactuals:
- Captions, 429. The caption endpoints my pipeline hits are the ones that throttled me hardest in past anonymous testing. Signed in, I rarely see 429 there; signed out, it’s the first wall I hit. I can’t claim this is universal — it’s the pattern on the surfaces I use.
- Audio, 403. The low-bitrate audio endpoint I fetch refused the request. Whether anonymous requests are always refused I can’t prove; what I can say is that in my pipeline, a request without the session’s credentials got 403 that night, every time.
- Recommendation feed, skipped. That stage reads the signed-in homepage. With no session it would have returned generic content, which the pipeline would have wasted quota parsing, so the script’s guard kicked in and skipped it.
If I’d rotated the proxy and retried blind, the 403 would most likely have persisted and I’d have burned twenty minutes chasing an IP that the evidence already argued against. I say “most likely” because I didn’t run that experiment — I had a cheaper probe with a clearer answer.
The probe order I now use before any retry
The general rule I extracted, and the reason I’m writing this down: when authenticated calls fail and anonymous calls succeed through the same exit node, check the credentials before the network. Not because the IP is proven innocent — because the credential layer is cheaper to inspect and, in my setup, fails silently far more often than the route does.
The cheapest probe order, most to least informative per second spent:
- Dump cookies over CDP and count them, scoped to the site. Single digits on a site that stores dozens = session death, case closed enough to act on.
- One anonymous request through the same node (RSS, a public API, a status page). If it succeeds, the node routes fine.
- Only then consider the node — and even then, rotate with a hypothesis, not as a reflex.
Step 1 is nearly free and I now run it before any retry. Three cookies versus dozens is a one-glance verdict.
Health reported at the wrong layer is the recurring theme
This is the same class of failure I wrote about in read the profile before you drive the browser — automation that reports health at the wrong layer. A tab being alive tells you the process is alive. It tells you nothing about the session, and on this stack the session is the part you actually depend on.
Two cheap changes came out of it
- The scan now dumps cookie count as a preflight. Below threshold, it logs
session deadand stops before burning any quota — no more 429/403 archaeology. - The node-rotation playbook now has an explicit precondition: don’t rotate while an anonymous probe through the same node still succeeds and the credential layer is uninspected. Credentials first, network second.
The underlying death was unglamorous: the browser profile’s cookie store had stopped persisting (the file on disk was gone while the process kept running from memory), so a restart would have surfaced it immediately. The recovery is one manual re-login — a human task, logged as such, not something to engineer around.
One session, two HTTP statuses and a skipped stage, zero useful logs from the thing that died. The probes you layer in front of a flaky external dependency are only as good as their ability to tell “the network is broken” from “your credentials evaporated”. Count the cookies first.