If you're a senior scraping engineer or security researcher who has stared at a Challenge page from Akamai in 2026, you already know the problem: a single mismatched field in your sensor_data payload invalidates your _abck cookie, and the next request is silently flagged. This Akamai Bot Manager v2 Deep-Dive walks through every layer of the detection stack — from the bmak telemetry engine to the X25519MLKEM768 post-quantum key share now default in Chrome 131+ — and shows how legitimate, authorized automation can pass cleanly using residential proxies and a properly instrumented browser context.
Legal & ethical caveat: The techniques below are for authorized security research, penetration testing with written scope, and legitimate automation that complies with the target site's Terms of Service. Unauthorized access to protected systems may violate the Computer Fraud and Abuse Act (CFAA) and GDPR Article 32. Always verify you have permission before testing.
How Akamai Bot Manager v2 Scores Automation
Akamai Bot Manager v2 is not a single check — it's a continuous server-side trust score that aggregates dozens of signals across the lifetime of a session. Unlike v1, which issued a one-shot challenge and moved on, v2 re-evaluates trust on every request. The score is updated based on behavioral telemetry, network reputation, TLS/HTTP fingerprints, and cookie state. If any signal drifts outside the expected distribution for the claimed User-Agent, the score drops and the session is either challenged, throttled, or silently degraded.
The core cookie pair is _abck and ak_bmsc. The ak_bmsc cookie is set early — often on the first HTTP response — and tracks a session identifier that Akamai's edge uses to correlate requests. The _abck cookie is the real trust token. It encodes a server-side verdict: ~-1~ means the challenge has not been solved, ~0~ means the session passed, and any other numeric value indicates a suspicious score that will trigger a challenge on the next sensitive request. The _abck cookie is only minted after the sensor.js (loaded as bmak) posts a valid sensor_data payload to Akamai's telemetry endpoint.
The Signal Stack at a Glance
| Signal Layer | What It Checks | Failure Mode |
|---|---|---|
| IP reputation (ASN, geo, type) | Datacenter vs residential, known proxy lists, geo consistency | Pre-scored as bot; _abck never reaches ~0~ |
| TLS fingerprint (JA3/JA4) | Cipher suite order, extensions, supported groups | Instant flag if mismatch with claimed UA |
| HTTP/2 SETTINGS frame | SETTINGS values, header order, WINDOW_UPDATE | Flagged as non-browser client |
| sensor_data payload | Mouse, scroll, touch, timing, screen, GPU, battery | Single field mismatch invalidates _abck |
| Behavioral analytics | Event cadence, entropy of mouse curves, dwell time | Score degradation over session |
Technical Context: Why This Problem Exists
Akamai's detection model exists because headless browsers and HTTP clients have become increasingly good at mimicking real browsers — but they're not perfect. The fundamental insight behind Bot Manager v2 is that consistency across layers is harder to fake than any single layer. A real Chrome 131 browser on Windows 11 produces a specific JA4 fingerprint, a specific HTTP/2 SETTINGS frame, a specific set of WebGL renderer strings, and a specific distribution of mouse event timings. If your automation stack claims to be Chrome 131 on Windows but your TLS ClientHello was generated by Python's ssl module (which uses OpenSSL, not BoringSSL), the JA4 hash won't match — and Akamai knows instantly.
The sensor_data payload is the most sophisticated layer. It's a serialized, obfuscated blob generated by bmak — Akamai's client-side telemetry script. The script collects over 100 signals, including:
- Mouse events: movement deltas, timestamps, click coordinates, and the entropy of the movement curve. Linear mouse paths with zero acceleration are an instant red flag.
- Scroll events: velocity, direction changes, and whether scroll is wheel-based or touch-based.
- Touch events: pressure values, touch area, multi-touch coordinates (on mobile).
- Screen and GPU properties:
navigator.platform,screen.width,screen.height,devicePixelRatio, WebGL renderer/vendor strings, and canvas fingerprint hashes. - Timing data:
performance.now()deltas between events,Date.now()consistency, and the time between page load and first interaction. - Environment probes: presence of
window.webdriver,navigator.pluginslength,navigator.languagesarray,Notification.permission, and battery API values where available.
The payload is then encrypted and posted to Akamai's telemetry endpoint (typically /_bm/... or a similar path). The server validates the payload against the claimed User-Agent and the session's IP reputation. If any field is inconsistent — for example, the payload claims navigator.platform === "Win32" but the WebGL renderer string is Apple M2 — the _abck cookie is set to a non-zero suspicious value and the session is flagged.
2026 Protocol Signals: Post-Quantum, JA4, and HTTP/2
In 2026, the protocol-level fingerprinting landscape has shifted significantly. Three signals matter most:
1. X25519MLKEM768 Post-Quantum Key Share
As of Chrome 131 (released late 2024 and now the dominant browser version in 2026), the default TLS ClientHello includes a post-quantum key share using X25519MLKEM768 (formerly known as X25519Kyber768Draft00). This adds a ~1,184-byte key share to the ClientHello, which changes the JA3/JA4 fingerprint hash entirely. If your automation client does not include this key share — or includes it in the wrong position — your JA4 fingerprint will not match any real Chrome 131+ browser. Most Python HTTP libraries (requests, httpx with default SSL) and even Playwright's bundled Chromium do not enable this by default, creating an immediate detection vector.
The JA4 fingerprint, as defined by the FoxIO JA4 specification, hashes the TLS version, cipher suite list, extensions, and signature algorithms in a deterministic order. The format is JA4 = t(i_4bytes)_c(cipher_list)_e(extensions)_s(sig_algs). For Chrome 131 on Windows, the JA4 string is something like t13d1516h2_8daaf6152771_b0da82dd1658 (the exact hash depends on extension order). If your client produces a different JA4, Akamai's edge can compare it against the User-Agent in milliseconds.
2. JA4 TLS Fingerprint Consistency
The JA4 fingerprint must agree with the claimed User-Agent. Akamai maintains a mapping of known JA4 hashes per browser version and OS. If you claim Chrome/131.0.0.0 on Windows but your JA4 matches Firefox 128, you're flagged before sensor_data is even evaluated. This is why tools like curl-impersonate or custom Go TLS libraries (e.g., utls) are necessary — they can reproduce the exact BoringSSL ClientHello that Chrome produces, including the post-quantum key share.
3. HTTP/2 SETTINGS Fingerprint
Beyond TLS, Akamai inspects the HTTP/2 SETTINGS frame. Chrome sends specific values for SETTINGS_HEADER_TABLE_SIZE (65536), SETTINGS_MAX_CONCURRENT_STREAMS (1000), SETTINGS_INITIAL_WINDOW_SIZE (6291456), and SETTINGS_MAX_HEADER_LIST_SIZE (262144). The order of these settings and the presence of WINDOW_UPDATE frames must match. Python's httpx with HTTP/2 support uses hyper-h2, which sends a different SETTINGS frame than Chrome. This creates a second fingerprint mismatch that Akamai checks independently of JA4.
Why Residential Proxies Are Required
Akamai weights IP reputation heavily in its trust score — arguably more than any other single signal. The reason is simple: IP reputation is the hardest signal to fake at scale. Datacenter IP ranges from AWS, GCP, Azure, DigitalOcean, and OVH are pre-scored as bot before any other signal is evaluated. This means even a perfect sensor_data payload and a flawless JA4 fingerprint will not produce a ~0~ _abck cookie if the request originates from a datacenter ASN.
Akamai's IP scoring considers:
- ASN type: Residential ISP (e.g., Comcast, Deutsche Telekom, NTT) vs hosting provider vs cloud provider.
- Historical behavior: Whether the IP has been seen making high-volume automated requests across Akamai's customer base.
- Geo consistency: Whether the IP's geo matches the timezone and locale claimed in the browser environment.
- IP age and stability: New or frequently rotating IPs from known proxy pools receive lower trust scores.
This is why residential proxies are non-negotiable for passing Akamai Bot Manager v2. Mobile proxies (4G/5G carrier IPs) can also work well and sometimes receive even higher trust scores, but they're slower and more expensive. Datacenter proxies are effectively useless against Akamai v2 for any site with moderate protection settings.
A Worked Approach: ProxyHat Residential Proxies + Stealth Browser
Below is a legitimate, authorized approach for passing Akamai Bot Manager v2 using ProxyHat residential proxies routed through a real browser context. This setup is appropriate for authorized monitoring, security research with written scope, and compliance auditing — not for credential stuffing, ticket fraud, or any activity that violates the target's Terms of Service.
Step 1: Configure the Residential Proxy
Route your browser traffic through ProxyHat's residential gateway. Use a sticky session so the IP doesn't rotate mid-session (which would invalidate _abck):
# HTTP proxy with sticky session and US geo-targeting
export HTTP_PROXY="http://user-session-research01-country-US:pass@gate.proxyhat.com:8080"
export HTTPS_PROXY="http://user-session-research01-country-US:pass@gate.proxyhat.com:8080"
# SOCKS5 alternative (use port 1080)
export ALL_PROXY="socks5://user-session-research01-country-US:pass@gate.proxyhat.com:1080"
The session-research01 flag ensures you get the same residential IP for the duration of your session. The country-US flag geo-targets to a US residential IP, which should match your browser's navigator.language and timezone settings.
Step 2: Launch a Real Browser with Consistent Fingerprints
Use Playwright (or Puppeteer) with a real Chromium build — not headless mode by default, since Chrome's --headless=new still leaks signals in 2026. Patch the environment for consistency:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(
headless=False,
proxy={
"server": "http://gate.proxyhat.com:8080",
"username": "user-session-research01-country-US",
"password": "pass"
},
args=[
"--disable-blink-features=AutomationControlled",
"--disable-features=IsolateOrigins,site-per-process",
]
)
context = browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/131.0.0.0 Safari/537.36",
viewport={"width": 1920, "height": 1080},
locale="en-US",
timezone_id="America/New_York",
)
page = context.new_page()
# Remove webdriver flag
page.add_init_script("""
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
// Ensure plugins array is non-empty (Chrome has PDF plugin)
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3, 4, 5]
});
""")
page.goto("https://target-site.com")
# Wait for _abck cookie to settle
page.wait_for_timeout(5000)
# Verify _abck contains ~0~ (passed)
cookies = context.cookies()
abck = [c for c in cookies if c["name"] == "_abck"]
print(f"_abck value: {abck[0]['value'] if abck else 'NOT SET'}")
browser.close()
Step 3: Generate Realistic Behavioral Telemetry
The sensor_data payload requires genuine mouse movement and interaction. A page that loads and immediately makes API calls without any mouse events will produce a suspicious bmak payload. Inject realistic behavior:
import random
import math
def simulate_human_mouse(page):
"""Generate Bezier-curve mouse movements with realistic timing."""
for _ in range(random.randint(3, 7)):
start_x = random.randint(100, 800)
start_y = random.randint(100, 600)
end_x = random.randint(100, 800)
end_y = random.randint(100, 600)
steps = random.randint(15, 40)
for i in range(steps):
t = i / steps
# Quadratic Bezier with random control point
ctrl_x = (start_x + end_x) / 2 + random.randint(-100, 100)
ctrl_y = (start_y + end_y) / 2 + random.randint(-100, 100)
x = (1-t)**2 * start_x + 2*(1-t)*t * ctrl_x + t**2 * end_x
y = (1-t)**2 * start_y + 2*(1-t)*t * ctrl_y + t**2 * end_y
page.mouse.move(x, y)
page.wait_for_timeout(random.randint(8, 25))
# Random scroll
page.mouse.wheel(0, random.randint(100, 500))
page.wait_for_timeout(random.randint(500, 2000))
simulate_human_mouse(page)
Step 4: Verify Cookie State Before Proceeding
After the sensor_data payload is posted (typically within 2–5 seconds of page load), check the _abck cookie. If it contains ~0~, the session has passed. If it contains ~-1~, the challenge hasn't been solved yet — wait longer or check for a CAPTCHA redirect. If it contains any other numeric value, the session is flagged and you should rotate to a new residential IP via a new ProxyHat session.
Common Mistakes and Edge Cases
Mistake 1: Using Headless Mode Without Patches
Chrome's --headless=new flag in 2026 still sets navigator.webdriver = true and produces a different WebGL renderer string (SwiftShader) than headed Chrome. Akamai's bmak checks both. Always run in headed mode, or use Xvfb on Linux to provide a virtual display.
Mistake 2: IP Rotation Mid-Session
If your proxy rotates the IP between the initial page load (when _abck is minted) and subsequent API calls, Akamai will see a cookie from IP A being used from IP B. This triggers an immediate re-challenge. Always use sticky sessions — ProxyHat's session- username flag keeps the same IP for the session duration.
Mistake 3: Timezone/Locale Mismatch with Geo
If your ProxyHat session targets country-DE but your browser's timezone is set to America/New_York and locale is en-US, the sensor_data payload will contain a timezone offset of -300 (EST) while the IP resolves to Berlin. Akamai flags this instantly. Always match timezone and locale to the proxy geo:
# Germany-targeted session
proxy = {
"server": "http://gate.proxyhat.com:8080",
"username": "user-session-res02-country-DE",
"password": "pass"
}
context = browser.new_context(
locale="de-DE",
timezone_id="Europe/Berlin",
# ... rest of config
)
Mistake 4: Missing Post-Quantum Key Share in TLS
If you're using a custom HTTP client (not a real browser) for some requests in your pipeline, ensure your TLS library supports X25519MLKEM768. In Go with utls:
import (
"github.com/refraction-networking/utls"
)
spec := utls.ClientHelloSpec{
TLSVersMax: utls.VersionTLS13,
CipherSuites: []uint16{
utls.TLS_AES_128_GCM_SHA256,
utls.TLS_AES_256_GCM_SHA384,
utls.TLS_CHACHA20_POLY1305_SHA256,
},
Extensions: []utls.TLSExtension{
&utls.SupportedPointsExtension{SupportedPoints: []byte{0}},
&utls.KeyShareExtension{KeyShares: []utls.KeyShare{
{Group: utls.X25519MLKEM768, Data: make([]byte, 1184)},
{Group: utls.X25519, Data: make([]byte, 32)},
}},
// ... other Chrome 131 extensions
},
}
Mistake 5: Overlooking HTTP/2 SETTINGS Frame
Even with a perfect TLS fingerprint, a wrong HTTP/2 SETTINGS frame will flag you. If you're using curl-impersonate (which handles both TLS and HTTP/2), verify with Wireshark that the SETTINGS frame matches Chrome's values. The SETTINGS_HEADER_TABLE_SIZE of 65536 and SETTINGS_INITIAL_WINDOW_SIZE of 6291456 are the most commonly mismatched values.
ProxyHat-Specific Setup and Configuration
For Akamai-protected targets, the recommended ProxyHat configuration is:
| Parameter | Recommended Value | Why |
|---|---|---|
| Proxy type | Residential | Datacenter ASNs are pre-scored as bot by Akamai |
| Session mode | Sticky (session-xxx) | IP must stay constant for _abck validity |
| Geo-targeting | Match browser locale/timezone | Geo mismatch is an instant flag |
| Protocol | HTTP (port 8080) or SOCKS5 (port 1080) | Both work; HTTP is simpler for browser proxy config |
| Concurrency | 1 session per IP | Multiple sessions from one residential IP raises suspicion |
For city-level targeting (useful when the target checks IP geo against a claimed city):
# Berlin-targeted residential IP
http://user-session-res03-country-DE-city-berlin:pass@gate.proxyhat.com:8080
Check available locations on the ProxyHat locations page and review pricing for residential proxy plans. For broader scraping use cases, see our web scraping guide and SERP tracking documentation. Full API and configuration reference is at docs.proxyhat.com.
Where This Is Appropriate
The techniques described here are appropriate for:
- Authorized security research: Penetration testing with a signed scope agreement that explicitly includes bot-detection bypass testing.
- Legitimate monitoring: Monitoring your own infrastructure or services where you have explicit authorization to access via automation.
- Compliance auditing: Verifying that your own site's bot protection is functioning correctly by testing against it.
- Academic research: Published research on bot-detection systems, conducted with institutional review board approval where required.
These techniques are not appropriate for credential stuffing, credit card testing, ticket scalping, sneaker botting, ad fraud, or any activity that circumvents access controls on systems you don't own or have explicit authorization to test. The CFAA and equivalent laws in other jurisdictions treat unauthorized access as a crime regardless of the technical method used.
Key Takeaways
- Akamai Bot Manager v2 uses a continuous server-side trust score that re-evaluates on every request — it's not a one-shot challenge.
- The
_abckcookie is only minted as~0~(passed) whensensor_data, TLS fingerprint, HTTP/2 fingerprint, and IP reputation all agree with the claimed User-Agent. - In 2026, Chrome 131+'s
X25519MLKEM768post-quantum key share changes the JA4 fingerprint — your TLS stack must include it or you're instantly flagged. - Residential proxies are non-negotiable — datacenter ASNs are pre-scored as bot before any other signal is evaluated.
- Use ProxyHat sticky sessions (
session-flag) to keep the IP constant for the_abcklifetime, and match geo-targeting to your browser's timezone and locale. - Always verify authorization before testing. CFAA and GDPR apply.
Frequently Asked Questions
What is Akamai Bot Manager v2?
Akamai Bot Manager v2 is an enterprise bot-detection system that uses a continuous server-side trust score combining IP reputation, TLS/HTTP fingerprints (JA4, HTTP/2 SETTINGS), and client-side behavioral telemetry from the sensor.js/bmak engine. Unlike v1's one-shot challenge, v2 re-evaluates trust on every request and can silently degrade or challenge sessions at any point. The _abck cookie encodes the current trust verdict.
Why does Akamai Bot Manager v2 matter for proxy users?
Because IP reputation is weighted heavily in Akamai's trust score, the type of proxy you use directly determines whether _abck can reach ~0~ (passed). Datacenter ASNs are pre-scored as bot, meaning even a flawless browser fingerprint won't help. Residential or mobile proxies are required for any chance of passing. Additionally, mid-session IP rotation invalidates _abck, so sticky sessions are essential.
Which proxy type works best for Akamai Bot Manager v2?
Residential proxies from real ISP ASNs are the baseline requirement. Mobile (4G/5G) proxies can receive even higher trust scores due to carrier IP reputation, but they're slower and more expensive. Datacenter proxies are effectively useless against Akamai v2 on moderately protected sites. Use sticky sessions to maintain IP consistency for the _abck cookie lifetime, and geo-target to match your browser's locale and timezone settings.
How do you avoid blocks when implementing Akamai Bot Manager v2 bypass?
Ensure four layers of consistency: (1) use residential proxies with sticky sessions and geo-matched locale/timezone; (2) use a real browser (not headless) with navigator.webdriver removed; (3) ensure your TLS stack includes the X25519MLKEM768 post-quantum key share so JA4 matches Chrome 131+; (4) generate realistic mouse/scroll events so sensor_data passes validation. A single mismatched field invalidates the entire session.
Can I use Python requests or httpx to pass Akamai Bot Manager v2?
Not directly. Python's requests and httpx use OpenSSL, which produces a JA4 fingerprint that doesn't match any real browser. They also don't generate sensor_data. You need either a real browser (Playwright/Puppeteer with Chromium) or a TLS-impersonation library like curl-impersonate combined with a sensor_data generation approach. Even then, residential proxies are required for IP reputation.






