_abck cookie?Short answer: _abck is the main cookie of Akamai Bot Manager. It is not a ticket you earn once — it is a ledger the edge keeps rewriting. Every response can hand you a new value, and the value encodes a verdict about the sensor data your browser sent. If you capture an _abck and hold it still, it starts decaying immediately.
That single sentence explains most Akamai failures. People treat this cookie as an access token — cache it in Redis, share it between workers, reuse it across proxy pools — and then wonder why the same value that returned 200 for one request returns a challenge for the next. The cookie is a report about a session, and a session is a browser plus a network identity plus a request pattern.
A typical value looks like F1A2B3...~-1~YAAQ... — three parts separated by tildes:
| Position | What it holds | What it means in practice |
|---|---|---|
| 1st | A long hash of sensor data collected by bmak / the sensor script | Proves that a script ran and what it reported. Editing it invalidates the whole cookie. |
| 2nd | The verdict flag | 0 = unknown yet, 1 = seen as bot, ~0 or -1 = accepted. A 1 is the one that blocks you no matter how good your headers look. |
| 3rd | Issuance record (encoded timestamp and reference data) | Lets the edge judge how old the verdict is. Stale values get re-evaluated. |
The three-segment layout is what you will see on most properties today, but the format is not a public contract: values occasionally carry an extra segment or a different separator on newer deployments. Split on ~ and read the flag from the second position, but log the whole value when something behaves unexpectedly — the shape is how you notice a rollout.
| Flag | Reading | What to do |
|---|---|---|
0 | Sensor has not reported a verdict yet, or the report has not been processed | Wait for another response from the same context; do not send the cookie anywhere else in the meantime. |
~0 | Accepted, with the session registered | The normal steady state. Keep the jar, keep the IP. |
-1 | Accepted, and the value has been superseded by a newer one | Expect a fresh Set-Cookie; storing this one over the newer copy is a regression, not a refresh. |
1 | Classified as a bot for this session | No header change fixes this. The session is burned: new context, new exit IP, new sensor run. |
"Burned" is worth taking literally. Once the flag is 1, the value keeps reporting that verdict for the life of the cookie, so retrying with different Accept-Language or a new user agent produces the same challenge. Retrying faster makes it worse.
Akamai evaluates sessions continuously rather than once at a gate. Each response can revise the verdict, so the cookie you exported five minutes ago may already describe a session the edge now considers suspicious — for example because your request rate jumped, your IP changed, or your TLS fingerprint stopped agreeing with the user agent you claim.
This is the single most common failure in Akamai scraping: developers treat _abck like a login token, cache it, and reuse it across workers and IPs. It is closer to a browser session's heartbeat.
The useful pattern is one session per identity, with the jar replaced on every Set-Cookie rather than merged.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
ctx = browser.new_context(proxy={"server": PROXY}, locale="en-US")
page = ctx.new_page()
page.goto(url, wait_until="networkidle") # bmak sensor runs here
def flag(value: str) -> str:
parts = value.split("~")
return parts[1] if len(parts) > 1 else "?"
jar = {c["name"]: c["value"] for c in ctx.cookies()}
print(sorted(jar), "verdict:", flag(jar.get("_abck", "")))
# Keep using this ctx. A new browser context on the same IP starts a new
# sensor run, so the jar is only reusable together with the identity.
# Replace, never merge: an accepted value can be older than the one you hold.
import requests
s = requests.Session()
s.headers.update({"User-Agent": UA_USER_AGENT}) # same UA that earned the cookie
r = s.get(url)
for c in r.cookies:
s.cookies.set(c.name, c.value, domain=c.domain, path=c.path)
if r.status_code == 403 and "~1~" in s.cookies.get("_abck", ""):
pass # session burned: needs a new context and a new exit, not a retry
bm_sz — session/telemetry cookie, paired with _abck; must move with it.bm_sv — short-lived, appears around sensitive endpoints.ak_bmsc — older bot manager cookie, still present on some properties.Moving _abck without bm_sz, or the reverse, is a reliable way to look like a replay attack. Both are usually in the same Set-Cookie batch, which is why merging jar entries — instead of replacing them — quietly produces inconsistent pairs.
There are two real options and one that does not exist:
_abck for a given URL is the usual substitute — SolveHub handles Akamai tasks this way and bills per completed task._abck in hand| What you see | What it usually means | First thing to change |
|---|---|---|
403 with a Reference #18... or Reference #1... identifier | Bot Manager denied the request; the identifier is Akamai's trace, not a hint at what to retry | Check the flag in the cookie you sent before touching headers |
Flag is 1 | The session is already classified as a bot | New context, new exit IP — the existing cookie cannot recover |
Flag is ~0 but the response is a challenge page | Sensor data alone passed; the request pattern did not (rate, path order, missing referer) | Slow down and request like a browser visits, not like a crawler enumerates |
| Worked, then failed after a proxy switch | The verdict is bound to the session, and the IP is part of the session | Pin one exit per session; rotate sessions instead of hops |
Works from curl with an exported jar, fails under load | TLS fingerprint and HTTP/2 behaviour differ from the client that earned the value | Keep the same client stack, or re-earn the cookie in the stack you will use |
Can I decode _abck? You can decode the third segment's timestamp, but the first is a hash of sensor input. Decoding does not let you forge a valid one.
Why does a fresh _abck still get a 403? Often because the flag in segment two is 1 — the edge already decided the session is a bot, and the cookie is reporting that decision rather than granting access.
Do I need a new one per request? No. One per session, refreshed on the schedule the site enforces. Rotating it per request is itself a signal.
How long is _abck valid? There is no single published lifetime. The third segment dates the verdict, and the edge re-decides on its own schedule, so the only reliable rule is to replace the value on every response rather than wait for an expiry.
Do I need bm_sz too? Yes, on most properties. They are issued together and a mismatched pair looks like a replay.