Imperva, which many sites still call Incapsula, does not protect a page with one cookie. A single blocked request can set three session cookies, load a short bootstrap script and, on stricter sites, start a full browser sensor. The mistake that costs the most time is choosing the solver task from the vendor name instead of from what the block page actually loads. This guide shows how to read an Imperva block, how to choose between ImpervaCookie and ImpervaUtmvcCookie, which captured URLs and session cookies are required, and how to replay the result.
The Imperva cookies, one by one
Imperva uses several cookies for different jobs. Only two of them are produced by the solver tasks.
| Cookie | Set by | What it is | Solver task |
|---|---|---|---|
visid_incap_<id> |
Imperva's server | Visitor ID; long-lived | none, it comes from your session |
incap_ses_<n>_<id> |
Imperva's server | Session ID; short-lived | none, it comes from your session |
nlbi_<id> |
Imperva's server | Load-balancer and session stickiness | none, it comes from your session |
___utmvc |
The UT.mvc bootstrap script | Proof that the bootstrap ran in a real browser | ImpervaUtmvcCookie |
reese84 |
The Reese84 sensor | Proof that a full browser-fingerprint sensor ran | ImpervaCookie |
The first three are issued by the server on the first request, even on the 403. The last two are earned by running a script, which is the part a plain HTTP client cannot do.
Tell Reese84 from UTMVC
Open the blocked page through your proxy and look at what it loads. The decision comes from the page, not from the site's name.
| What the block page contains | Mechanism | Task |
|---|---|---|
A script from a site-specific sensor path, with or without an iframe named main-iframe |
Reese84 | ImpervaCookie |
Only a /_Incapsula_Resource?SWJIYLWA=… script |
UT.mvc | ImpervaUtmvcCookie |
| Both | Reese84 first; the page also runs UT.mvc | ImpervaCookie, then check the response |
| Neither, and a normal 200 | No Imperva challenge for this session | no task needed |
A Reese84 page is a short 403 interstitial. It loads the sensor asynchronously from a path unique to the site, and the sensor posts its collected browser data to that path. If the reply is accepted, the page sets the reese84 cookie. The sensor's reply also carries a renewal interval: the cookie is meant to be refreshed, so an old value needs a new solve and not a replay.
A UT.mvc page loads /_Incapsula_Resource with an SWJIYLWA query parameter. The script collects browser probes and writes a ___utmvc cookie with a very short lifetime. Some sites serve their normal page with only that bootstrap injected, and no Reese84 sensor exists. For such a site ImpervaUtmvcCookie is the correct task; do not expect a reese84 cookie from ImpervaCookie there.
The two chains are separate. Never set a ___utmvc value under the name reese84, or the reverse, and do not assume that clearing one clears every Imperva rule.
Create the task
Both tasks require websiteURL, userAgent, your sticky proxy and cookies containing a non-empty, script-visible incap_ses* cookie scoped to the protected page. There is no proxyless variant.
For Reese84, capture the sensor URL from the block, and its UT.mvc and iframe URLs only when that page has them:
{
"clientKey": "sur_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"task": {
"type": "ImpervaCookie",
"websiteURL": "https://www.example.com/",
"sensorUrl": "https://www.example.com/site-sensor.js",
"utmvcUrl": "https://www.example.com/_Incapsula_Resource?SWJIYLWA=SESSION",
"iframeUrl": "https://www.example.com/_Incapsula_Resource?incident_id=SESSION",
"cookies": "incap_ses_123_456=SESSION; visid_incap_456=VISITOR",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36",
"proxy": "http://user:pass@proxy.example.com:8080"
}
}
For ImpervaUtmvcCookie, replace the Reese84 URL fields with required scriptUrl containing the UT.mvc bootstrap URL; iframeUrl is optional for that task. Keep the session cookies, User-Agent and proxy unchanged.
cookies accepts a Cookie header value or the engine's NDJSON cookies. A cookie entry marked HttpOnly, scoped to another host/path, or containing an empty session value cannot supply the script-visible session that the native flow requires. Missing inputs are rejected before charging.
An unsupported userAgent returns ERROR_WRONG_USERAGENT with supportedUserAgents.
Capture the required script and iframe URLs
No automatic URL discovery is performed. For ImpervaCookie, send sensorUrl from the blocked response. Add utmvcUrl and iframeUrl only when that page loads a UT.mvc bootstrap or has iframe#main-iframe; a "Pardon Our Interruption" page has neither. The legacy scriptUrl field is rejected for this task.
For ImpervaUtmvcCookie, send the exact /_Incapsula_Resource?SWJIYLWA=… URL as scriptUrl; iframeUrl is optional. Use absolute public HTTP(S) URLs and retain their query strings.
The two tasks do not accept interchangeable loaders. Replaying a UT.mvc value as reese84, or supplying only a Reese84 sensor to the UTMVC task, does not satisfy the other protection layer.
Poll and read the result
Poll getTaskResult every 3 seconds. The task has a 60-second budget.
{
"errorId": 0,
"status": "ready",
"solution": {
"reese84": "the cookie value"
}
}
The key is the cookie name of the task you chose: reese84 for ImpervaCookie, ___utmvc for ImpervaUtmvcCookie. Its value carries no attributes and there is no userAgent. cookies, when returned, maps every returned cookie name to its value.
Replay the cookie
Set the value on the protected site's domain and repeat the request through the same proxy with the same User-Agent. Keep the other session cookies from your own session when your flow needs them.
# imperva-python.py - solve Imperva Reese84 and request the protected page with the reese84
# cookie.
# Install: pip install requests
# Run: python imperva-python.py
import time
import requests
# Your SurSolver API key.
CLIENT_KEY = "sur_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# The challenged page, exactly as it shows the challenge.
TARGET_URL = "https://example.com/page"
# The proxy for the solve and the replay: http://user:pass@host:port or socks5://host:port.
PROXY_URL = "http://username:password@proxy.example.com:8080"
# The Reese84 sensor script URL from the current block page.
SENSOR_URL = "https://example.com/sensor.js"
# The SWJIYLWA UT.mvc bootstrap URL, when that same block page loads one.
UTMVC_URL = None
# The CWUDNSAI URL of iframe#main-iframe, when that same block page has one.
IFRAME_URL = None
# Existing session cookies as a Cookie header value (name=value; name2=value2).
SESSION_COOKIES = "incap_ses_123=YOUR_CAPTURE; visid_incap_123=YOUR_CAPTURE"
# The User-Agent the solve runs with; send the result with this same user agent.
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36"
# Text that appears only in a response the site accepted.
SUCCESS_TEXT = "PASTE_ACCEPTED_MARKER"
API = "https://api.sursolver.com"
POLL_ATTEMPTS = 60
def call(path, body):
# API errors are HTTP 200 with errorId 1; anything else is a transport failure.
response = requests.post(f"{API}{path}", json=body, timeout=30)
response.raise_for_status()
data = response.json()
if data["errorId"] != 0:
raise RuntimeError(f'{data["errorCode"]}: {data["errorDescription"]}')
return data
def solve(task):
created = call("/createTask", {"clientKey": CLIENT_KEY, "task": task})
for _ in range(POLL_ATTEMPTS):
result = call("/getTaskResult", {"clientKey": CLIENT_KEY, "taskId": created["taskId"]})
if result["status"] == "ready":
return result["solution"]
time.sleep(3)
raise TimeoutError(f'task {created["taskId"]} was not ready in {POLL_ATTEMPTS} polls')
def without_empty(fields):
# Optional task fields are sent only when they have a value.
return {name: value for name, value in fields.items() if value not in (None, "")}
PROXIES = {"http": PROXY_URL, "https": PROXY_URL}
def main():
solution = solve({
"type": "ImpervaCookie",
"websiteURL": TARGET_URL,
"sensorUrl": SENSOR_URL,
"cookies": SESSION_COOKIES,
"userAgent": USER_AGENT,
**without_empty({
"utmvcUrl": UTMVC_URL,
"iframeUrl": IFRAME_URL,
}),
"proxy": PROXY_URL,
})
# Replay with the user agent the solve ran with, through the same proxy.
headers = {"User-Agent": USER_AGENT}
cookies = dict(part.strip().split("=", 1) for part in (SESSION_COOKIES or "").split(";")
if "=" in part)
cookies["reese84"] = solution["reese84"]
cookies = {
**cookies,
**solution.get("cookies", {}),
"reese84": solution["reese84"],
}
response = requests.get(
TARGET_URL,
headers=headers,
cookies=cookies,
proxies=PROXIES,
timeout=30,
)
if not response.ok or SUCCESS_TEXT not in response.text:
raise SystemExit(f"The site did not accept the result (HTTP {response.status_code}).")
print("The site accepted the result.")
if __name__ == "__main__":
main()
For the separate UTMVC layer, use this script; it replaces only ___utmvc:
# imperva-utmvc-python.py - solve Imperva UTMVC and request the protected page with the ___utmvc
# cookie.
# Install: pip install requests
# Run: python imperva-utmvc-python.py
import time
import requests
# Your SurSolver API key.
CLIENT_KEY = "sur_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# The challenged page, exactly as it shows the challenge.
TARGET_URL = "https://example.com/page"
# The proxy for the solve and the replay: http://user:pass@host:port or socks5://host:port.
PROXY_URL = "http://username:password@proxy.example.com:8080"
# The complete SWJIYLWA UT.mvc bootstrap URL from the current block page.
SCRIPT_URL = "https://example.com/challenge.js"
# The CWUDNSAI main-iframe URL when this page includes one.
IFRAME_URL = None
# Existing session cookies as a Cookie header value (name=value; name2=value2).
SESSION_COOKIES = "incap_ses_123=YOUR_CAPTURE; visid_incap_123=YOUR_CAPTURE"
# The User-Agent the solve runs with; send the result with this same user agent.
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36"
# Text that appears only in a response the site accepted.
SUCCESS_TEXT = "PASTE_ACCEPTED_MARKER"
API = "https://api.sursolver.com"
POLL_ATTEMPTS = 60
def call(path, body):
# API errors are HTTP 200 with errorId 1; anything else is a transport failure.
response = requests.post(f"{API}{path}", json=body, timeout=30)
response.raise_for_status()
data = response.json()
if data["errorId"] != 0:
raise RuntimeError(f'{data["errorCode"]}: {data["errorDescription"]}')
return data
def solve(task):
created = call("/createTask", {"clientKey": CLIENT_KEY, "task": task})
for _ in range(POLL_ATTEMPTS):
result = call("/getTaskResult", {"clientKey": CLIENT_KEY, "taskId": created["taskId"]})
if result["status"] == "ready":
return result["solution"]
time.sleep(3)
raise TimeoutError(f'task {created["taskId"]} was not ready in {POLL_ATTEMPTS} polls')
def without_empty(fields):
# Optional task fields are sent only when they have a value.
return {name: value for name, value in fields.items() if value not in (None, "")}
PROXIES = {"http": PROXY_URL, "https": PROXY_URL}
def main():
solution = solve({
"type": "ImpervaUtmvcCookie",
"websiteURL": TARGET_URL,
"scriptUrl": SCRIPT_URL,
"cookies": SESSION_COOKIES,
"userAgent": USER_AGENT,
**without_empty({
"iframeUrl": IFRAME_URL,
}),
"proxy": PROXY_URL,
})
# Replay with the user agent the solve ran with, through the same proxy.
headers = {"User-Agent": USER_AGENT}
cookies = dict(part.strip().split("=", 1) for part in (SESSION_COOKIES or "").split(";")
if "=" in part)
cookies["___utmvc"] = solution["___utmvc"]
cookies = {
**cookies,
**solution.get("cookies", {}),
"___utmvc": solution["___utmvc"],
}
response = requests.get(
TARGET_URL,
headers=headers,
cookies=cookies,
proxies=PROXIES,
timeout=30,
)
if not response.ok or SUCCESS_TEXT not in response.text:
raise SystemExit(f"The site did not accept the result (HTTP {response.status_code}).")
print("The site accepted the result.")
if __name__ == "__main__":
main()
Replay ___utmvc right away: the bootstrap gives it a very short lifetime, so a value kept for later may already be gone. A reese84 cookie lives longer, but plan to solve again when the sensor's renewal interval passes.
A ready task is not a 200
A completed task means the cookie was generated. It does not certify that the site will return its normal page. Imperva evaluates more than one cookie: it can still block the IP, send a stricter challenge, or reject a session whose other cookies do not match. Always check the protected response yourself.
| Symptom | Likely cause | Fix |
|---|---|---|
| Still 403 after replay | The IP is blocked, or other rules apply | Use a different sticky proxy session |
| Same block page again | The cookie was set on the wrong domain or name | Check the name matches the task type and the domain matches the request host |
___utmvc works once, then fails |
The cookie expired | Replay immediately, or solve again before each burst |
reese84 works, then 403 after a while |
The sensor token needs renewing | Solve again instead of reusing an old value |
| Result looks like the wrong cookie | ImpervaCookie on a UT.mvc-only page |
Switch to ImpervaUtmvcCookie |
ERROR_FAILED |
The URL served no Imperva challenge, or the scripts could not load | Re-capture the block through your proxy; the charge is refunded once |
A failed or timed-out task returns its original charge once.
Checklist
- Open the block page through your production proxy and note which scripts it loads.
- Use
ImpervaCookiewhen the page loads a Reese84 sensor; useImpervaUtmvcCookiefor theSWJIYLWAbootstrap alone. - Capture all required URLs and script-visible
incap_ses*session cookies from that same block. - Send a sticky proxy and a complete User-Agent from
supportedUserAgents. - Set the cookie under the right name, replay through the same proxy, and check the response.
The Imperva solver page lists the fields at a glance. The API reference documents ImpervaCookie and ImpervaUtmvcCookie, and Proxies for captcha solving explains how to keep one sticky session.
Current input and replay contract
Both tasks require websiteURL, userAgent, a sticky proxy and script-visible incap_ses* session cookies. Reese84 requires sensorUrl; utmvcUrl and iframeUrl are optional and sent only when the page has them. UTMVC requires scriptUrl; its iframeUrl is optional. No automatic URL discovery is performed; one loader does not replace the other.
solution.reese84 or solution.___utmvc is only that cookie's value. Preserve the application's other cookies. If the site uses both layers, carry the first layer's cookies into the second solve and replay. The shared scripts take SESSION_COOKIES as a Cookie header string and replace only their own cookie. A ready cookie is not a guarantee that a separate application policy allows access. See the two complete Imperva flows.