Akamai Bot Manager has no widget to click, so there is nothing to point a solver at until you know what is blocking you. This post does the diagnosis first: you will be able to confirm that a site runs Akamai, name the protection layer that is blocking you, send an AkamaiCookie task through SurSolver, and replay the returned cookies so the edge accepts them.
Check whether the site runs Akamai
Akamai Bot Manager sits at the CDN edge and scores each request. A heavily obfuscated script collects browser and device telemetry and posts it back as {"sensor_data": "..."}; the edge then allows, rate-limits, challenges or blocks the traffic. Nothing is drawn on the page, so you recognise it from what the responses carry.
| Signal | What to look for |
|---|---|
| Cookies | _abck (the validation token), bm_sz (a seed set on the first response), ak_bmsc (HTTP-only, lives for hours), bm_sv, bm_mi. bm_s / bm_sc point to the SBSD layer; sec_cpt belongs to the 428 challenge. |
| Script URL | A same-origin script with a random-looking path that changes between page loads, serving obfuscated JavaScript. |
| Response headers | X-Akamai-* headers such as X-Akamai-Transformed, plus akamai-grn and x-akamai-request-id. |
| Response behaviour | 403 with an "Access Denied" or "Pardon Our Interruption" page, a 429 after a single request, a fake ERR_HTTP2_PROTOCOL_ERROR that looks like downtime, HTTP 428 for the sec-cpt layer. |
| Sensor endpoints | A POST of sensor_data to the script URL itself; /_sec/cp_challenge/verify and /_sec/verify?provider= for the 428 layer. A successful sensor POST answers 201. |
Block-page wording differs from site to site, so lean on the cookie cluster and the script rather than the page text. _abck plus bm_sz plus an obfuscated same-origin script is the strongest combination.
Read the tail of the _abck cookie
The end of the _abck value tells you how far the handshake got. Treat it as a convention, not a contract: some sites need a fixed number of sensor posts, and some never show the final state.
| Tail | Reads as |
|---|---|
~-1~ |
A challenge is outstanding; the edge has not accepted any sensor yet. |
~0~-1~ |
A sensor arrived but was not enough. |
~0~ |
The sensor was accepted. |
Do not judge a cookie by its one-year Expires date. The cookie itself lives for about a year, but the validated state lapses within minutes to hours, so a cookie that looks fresh can already be worthless.
Work out which layer blocks you
Akamai stacks several protections, and clearing one while another is active still gets you blocked. Match what you see to the row below.
| What you observe | Layer | With SurSolver |
|---|---|---|
_abck and bm_sz are set, the page loads, but login, cart or checkout calls get challenged |
Web sensor (_abck) |
AkamaiCookie |
HTTP 428 with JSON containing sec-cp-challenge: true and a provider field |
sec-cpt, a proof-of-work layer beside _abck |
Not a separate task type; the catalog lists only AkamaiCookie |
Blocked before any real HTML; bm_s, bm_sc, bm_so cookies or an SBSD script URL |
SBSD, which sits in front of the content and often needs _abck as well |
Not a separate task type |
| Calls from a native Android or iOS app are rejected and the app embeds Akamai's mobile library | BMP, the mobile counterpart of the web sensor | Not offered |
| You already control TLS, IP and headers and only want sensor payloads computed | Sensor payloads | Not offered; SurSolver returns cookies, not payloads |
The public catalog (GET /v1/task-types) lists exactly one Akamai task: AkamaiCookie, with the result keys cookies and userAgent. Neither the catalog nor the solver guide says whether that solve also clears sec-cpt or SBSD. If your target shows those layers, run a single task first and check the result against the site before you build anything around it.
Collect the task parameters
| Field | Required | What to send |
|---|---|---|
websiteURL |
Yes | The page whose first load serves the sensor, usually the login, checkout or product page rather than the homepage. A wrong URL means the sensor script is never found. |
proxy |
Yes | The exit IP the cookies will be bound to. This type has no proxyless form. A four-part string is read as user:password:host:port; see Proxies for every accepted format. |
userAgent |
No | An optional parameter. The docs do not say whether the solve uses it, so replay with the userAgent the result returns rather than assuming yours was used. |
Residential or mobile exits are the least likely to be scored harshly; datacenter ranges can be soft-blocked before the sensor even runs.
Create the task and poll for the result
The envelope is the same as for every SurSolver type: createTask answers {"errorId":0,"taskId":"...","status":"idle"}, getTaskResult answers processing until the task is ready. Poll every 3 seconds. API errors arrive as HTTP 200 with errorId: 1; an unexpected fault is an HTTP 500 without errorId. The docs set no polling ceiling, so choose your own deadline.
import os
import time
import requests
API = 'https://api.sursolver.com'
API_KEY = os.environ['SURSOLVER_API_KEY']
POLL_SECONDS = 3
DEADLINE_SECONDS = 180
REQUEST_TIMEOUT = 30
TARGET_URL = 'https://www.example.com/login'
USER_AGENT = (
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36'
)
PROXY = 'http://user:password@203.0.113.10:8000'
def call(path, body):
response = requests.post(f'{API}{path}', json=body, timeout=REQUEST_TIMEOUT)
response.raise_for_status() # HTTP 500 carries no errorId
data = response.json()
if data.get('errorId'):
raise RuntimeError(f"{data['errorCode']}: {data.get('errorDescription')}")
return data
def solve_akamai():
created = call('/createTask', {
'clientKey': API_KEY,
'task': {
'type': 'AkamaiCookie',
'websiteURL': TARGET_URL,
'userAgent': USER_AGENT,
'proxy': PROXY,
},
})
task_id = created['taskId']
deadline = time.monotonic() + DEADLINE_SECONDS
while time.monotonic() < deadline:
time.sleep(POLL_SECONDS)
result = call('/getTaskResult', {'clientKey': API_KEY, 'taskId': task_id})
if result['status'] == 'ready':
return result['solution']
raise TimeoutError(f'task {task_id} still processing after {DEADLINE_SECONDS}s')
A ready result carries the cookies and, when the solver reports one, the user agent they were earned with:
{
"errorId": 0,
"status": "ready",
"solution": {
"cookies": [
{ "name": "_abck", "value": "D9510DC4D434428407C86AB269DE00FB~-1~YAAQ..." },
{ "name": "bm_sz", "value": "969BC97CE529B4D5B3524F8B41F04205~YAAQ..." },
{ "name": "ak_bmsc", "value": "2A211393DCE7882215589B02B341941D~000000..." }
],
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/144.0.0.0 Safari/537.36"
}
}
userAgent is conditional. When it is present, replay with it; when it is absent, the result does not say which browser earned the cookies, so the script falls back to your own user agent and the first replay tells you whether that works. Which cookie names appear can vary; replay every entry in the list, with its domain and path when the solver reports them.
If your own deadline expires, the task is still charged and still readable for the retention window (30 minutes from creation by default), so you can fetch it later with the same taskId.
Replay the cookies from the same connection
Set every cookie on a session that uses the same proxy and the same user agent as the solve, then request the protected page.
import requests
solution = solve_akamai()
session = requests.Session()
session.proxies = {'http': PROXY, 'https': PROXY}
session.headers['User-Agent'] = solution.get('userAgent', USER_AGENT)
for cookie in solution['cookies']:
session.cookies.set(cookie['name'], cookie['value'], domain=cookie.get('domain'), path=cookie.get('path', '/'))
response = session.get(TARGET_URL, timeout=REQUEST_TIMEOUT)
print(response.status_code)
Plain requests presents Python's TLS fingerprint, not Chrome's. The edge compares the cookie against the live connection, including TLS and HTTP/2 characteristics and header order, so a replay can fail with the right IP and user agent. If it does, replay from a client that mirrors Chrome's TLS, or let a real browser such as Playwright carry the session. Browser headers and user agents covers what has to match.
Common failures
- A different IP, user agent or TLS fingerprint on replay. The cookies are refused, not merely downgraded. Keep one sticky proxy session for the solve and every request that uses the cookies.
- Reusing an old jar. Trust lasts from a few protected requests to a few hours, and protected actions typically consume it. Solve again after a challenge instead of caching the cookies.
- The wrong URL. Sending the homepage when the sensor is served on the login page gives the solver nothing to work with.
- A datacenter proxy. It can be blocked before the sensor runs; see Proxies for captcha solving.
- A layer that was never cleared. A persistent 428, or a block before any HTML, points to sec-cpt or SBSD rather than a bad
_abck. - Solving blind. A task is charged when it is accepted, and a task that finishes as failed automatically returns its original charge once. Confirm the Akamai signals above before you create one.
Next steps
Create an AkamaiCookie task with websiteURL, proxy and userAgent, poll getTaskResult every 3 seconds, and replay the cookies from the same proxy. The Akamai guide covers recognition and parameters in more depth, and the public catalog (GET /v1/task-types) lists the accepted names and result keys. If you are unsure which captcha a site uses at all, start with identify any captcha and extract its parameters.