The Web Scraping Club

The Web Scraping Club

The LAB #116: Warming an Imperva reese84 cookie, and replaying it without a browser

A tenth of a cent buys thirteen minutes of scraping, from any IP I tried

Pierluigi Vinciguerra's avatar
Pierluigi Vinciguerra
Sep 24, 2026
∙ Paid

Imperva is one of the anti-bots we didn’t write a lot about in the past, probably because, for some reason I ignore, I’ve never encountered it in my career of scraping ecommerce websites (or maybe, if I encountered, it was so easy to bypass that I didn’t notice that).

To fill this gap, today I’m creating a case study for smythstoys.com, the Irish site of Smyths Toys. I picked it because a reader described the exact problem on the r/webscraping subreddit: Smyths runs Imperva, the product pages are server-rendered HTML, and the one internal endpoint that returns stock is protected too. The idea in that thread was to keep one hot cookie per proxy, forged using a browser, and replay it over cheap datacenter IPs. I wanted to check three things: does that actually work, how long does the cookie last, and when does it eventually break?

This time I worked two ways at once. I built a bypass that warms a session with a browser, solves the challenge, and then runs on a plain HTTP client. And I ran Manus against the same site to read the protection from the inside (so I could explain why the bypass keeps working, instead of only showing that it does). The bypass is mine, while the deep read of the sensor, the token, and the renewal protocol is Manus’s, checked against my own captures where the two overlap.

Give your AI a web data layer – Decodo’s Web Scraping API turns any site into clean, structured data your models can actually use.

Activate starter plan

Manus, and how I used it here

Manus is an agent that pairs a language model with a sandboxed Linux VM and a Chromium browser. It can drive a page, run Node and Python, and instrument the browser while it executes, which is what makes it useful here. You may have noticed that in the latest The Lab issues I used that a lot: in THE LAB #114 against Kasada and THE LAB #115 against DataDome.
This is mainly for two reasons: it uses the sandboxed VMs, so it can spawn a browser and run tests in its virtual environment, and, at the same time, it’s not so heavily guardrailed, so these tasks can be performed with ease.

For this article, Manus hooked JSON.stringify and the btoa boundary before the page scripts ran, so it logged the exact sensor request and the clear-text fingerprint the moment they were built. Then it ran cold, warm and mutation matrices against the token endpoint. Its run was on 18 September 2026, in headless Chromium 151.0.7922.71, anonymous, thirteen page navigations, no credentials and no CAPTCHA solving. One detail from that setup matters later: its browser reported navigator.webdriver=true, so it announced itself as automated.

I trust the numbers Manus reported across those runs, and I checked the ones that agree with my own captures. Where I quote a Manus figure I say so, because I did not reproduce its in-browser instrumentation myself. Manus also did not vary the IP, the User-Agent or the TLS fingerprint, and it did not solve a CAPTCHA, so those parts of the story are mine.

The protection at a high level

Before jumping into the details, let’s see what happens if we cURL the target website:

$ curl -s -D - -A "Mozilla/5.0 ... Chrome/140.0.0.0 Safari/537.36" https://www.smythstoys.com/ie/en-ie/
HTTP/2 200
x-cdn: Imperva
x-iinfo: 10-32110005-0 NNNN RT(...) ...
set-cookie: visid_incap_2483049=...; Domain=.smythstoys.com; ...
set-cookie: incap_ses_416_2483049=...; Domain=.smythstoys.com; ...

The x-cdn: Imperva header and the visid_incap and incap_ses cookies are the Incapsula signature. Of course, what we receive it’s not the home page of the website but an error page. It’s a 1,158 byte HTML shell with an iframe that says “Request unsuccessful. Incapsula incident ID: ...”. So the edge already decided my plain client is not welcome, before any product page is served.

There are five pieces here, and it helps to name them before going deep on any one. The edge WAF answers the navigation with the interstitial (the “Pardon Our Interruption” page that sits between you and the shop), or with the real shop once you are cleared. A throwaway fingerprint cookie called ___utmvc is built in the browser and lives for about twenty seconds. The reese84 sensor is the real collector, two large obfuscated scripts of around 800 KB each loaded from paths that look like random english words. The token exchange is the POST that sends the sensor result and gets the reese84 token back. And the GeeTest CAPTCHA is what Imperva falls back to when the sensor result alone is not enough.


Tired of getting blocked while scraping the web?
ScrapingBee handles proxies, browsers, anti-bot systems, and retries so you can focus on your data. Get clean Markdown, JSON, or HTML from the web with up to a 99.9% success rate. ScrapingBee is SOC 2 Type II and GDPR compliant, and trusted by 4,000+ developers.

Discover ScrapingBee


Manus drew the whole thing as one diagram, which is the clearest way to see how these pieces connect.

The reese84 flow end to end, mapped from the Manus run. It shows the edge challenge and the two browser collectors, the short-lived ___utmvc helper and the reese84 interrogator. It then splits into the cold, warm and replacement token paths, and ends at the edge policy check. That last box is where a CAPTCHA-solved jar and an interrogation-only jar go different ways.

The server-side scoring is out of scope, for the simple reason that nobody outside Imperva can see it. Everything I claim below is something one of us saw live, in the cookie jar, or in the sensor code as it ran. We have covered the general idea before: cookies and sessions as a clearance store in THE LAB #94, and a browser-to-HTTP handoff in THE LAB #100. This is the same shape, applied to Imperva, with the extra question of what the token is tied to.

The bypass: warm a session, then run without a browser

The bypass has three tools, each for one job.

Scrapling does the warming. Its StealthySession launches a Chromium browser and keeps cookies across requests. I use it because it gives me a page_action callback with the real Playwright page inside, so I can watch the network and drive the challenge frame by hand.

CapSolver solves the CAPTCHA. Imperva shows a GeeTest challenge when the sensor alone is not enough, and CapSolver has a GeeTest task type that returns the three values GeeTest wants back.

curl_cffi does the replay. It sends HTTP requests with the TLS fingerprint of a real Chrome, without a browser, so I can test whether the warmed cookie works on its own.

All of it runs in the shared venv on Python 3.11. My code is in the 116-Imperva-Reese84 directory of The Lab repository, with the scripts and the captured results, so you can rerun every number that carries my name below.

When I warm a session with Scrapling and log every request on smythstoys.com, the order is always the same. The browser loads the home page and gets the interstitial. The sensor scripts load. The sensor POSTs its blob to a random path, and a second POST returns the token:

POST /mbit-And-Dirers-him-Face-and-sure-such-Parry-qui?d=www.smythstoys.com
{"token":"3:nHkG6Ry2bxW+gbWD+elLTg==:RZgGQ1gd...","renewInSec":699,"cookieDomain":"www.smythstoys.com"}

That token value becomes the reese84 cookie. The renewInSec is 699, so the browser is told to refresh the token in about eleven and a half minutes. The cookieDomain is the host, so the cookie is scoped to www.smythstoys.com. On Smyths this token alone was never enough for my headless Chromium. Every warming run ended on a GeeTest challenge, so I had to solve it.


Check the TWSC YouTube Channel


The challenge flow is readable in the interstitial frame. A GET to /_Incapsula_Resource?SWCNGEEC=... returns the GeeTest parameters:

{"challenge": "230a350828feeac904b737841e83ecd8", "gt": "ce33de396f8d04030f6eca8fbd225070", "new_captcha": true, "success": 1}

The gt was the same across every run, ce33de396f8d04030f6eca8fbd225070, which is the site’s GeeTest id. The challenge changes each time. When the widget is solved, the page POSTs the result to /_Incapsula_Resource?SWCGHOEL=gee&... with geetest_challenge, geetest_validate and geetest_seccode, then reloads the parent frame.

My warm_session.py does exactly that, from inside the frame. It reads the two URLs out of the frame’s HTML, calls the GET to get gt and challenge, sends those to CapSolver as a GeeTestTaskProxyLess task, and gets back the three values. Then it POSTs them to the SWCGHOEL=gee URL using the frame’s own fetch, so the request carries the session cookies, and reloads the page.

CapSolver returned a solution in about ten to twelve seconds each time. It’s not perfectly reliable: I saw it fail with ERROR_CAPTCHA_SOLVE_FAILED code 1001 on some challenges, so the script retries up to three times. GeeTest solves cost one dollar per thousand on CapSolver when I ran this, so a failed attempt followed by a good one is still a fraction of a cent. After the solved reload, the page title finally read “Smyths Toys Superstores | Buy Toys for Kids”, which is the real shop. Here is the tail of a real run, warmed through an Irish residential proxy:

attempt 1: challenge 6abbf70a... gt ce33de396f8d04030f6eca8fbd225070
capsolver solved in 10.3s
imperva captcha submit -> 200 '<html><head><script>window.parent.location.reload(true);</script></head>...'
SAVED status=REAL_AFTER_CAPTCHA cookies=[incap_ses, reese84, incap_sh, visid_incap, nlbi, nlbi]

Now the part that makes the whole thing worth doing: does the clearance survive without the browser? I take the cookie jar from that warmed session (the full set of cookies the browser collected) and replay it with curl_cffi, no browser, impersonating Chrome. I fetch the home page and the Magic The Gathering category page the reader mentioned:

jar: warm_pub01.json  status=REAL_AFTER_CAPTCHA  minted 86s ago
warm proxy (same exit)   | home      | 200  603618 REAL | 'Smyths Toys Superstores | Buy Toys for Kids'
warm proxy (same exit)   | category  | 200  471472 REAL | 'Magic The Gathering | Smyths Toys Ireland'
replay proxy             | home      | 200  603752 REAL | 'Smyths Toys Superstores | Buy Toys for Kids'
replay proxy             | category  | 200  471605 REAL | 'Magic The Gathering | Smyths Toys Ireland'
direct (no proxy)        | home      | 200  603751 REAL | 'Smyths Toys Superstores | Buy Toys for Kids'
direct (no proxy)        | category  | 200  471605 REAL | 'Magic The Gathering | Smyths Toys Ireland'

The warmed jar returns the real page from the same Irish residential IP that created it, from a datacenter IP in Ohio, and from my own connection in Italy. I ran the same jar from a second Irish residential IP too, with the same result. So, at least in my tests, the clearance is not bound to the minting IP. This is what makes the reader’s architecture work: you warm on a good residential IP, then you replay over whatever is cheapest.

I went further and varied the HTTP client itself, same warmed jar, direct connection:

chrome136 + Chrome UA (match)      | 200  467891 REAL
firefox135 + Firefox UA            | 200  467891 REAL
chrome136 + Firefox UA             | 200  467891 REAL
no impersonation + Chrome UA       | 200  467891 REAL

On this site, once the jar is warmed, the TLS fingerprint and the User-Agent stop mattering. Even curl_cffi with no impersonation, which sends a TLS handshake no browser would send, gets the real page. So the warmed reese84 works as a bearer token (a token that works for whoever presents it, with nothing tying it to one client): any client that presents the jar gets the real page back.

That is the working bypass. The rest of the article explains why it holds, using the Manus report.

Why the replay works

User's avatar

Continue reading this post for free, courtesy of Pierluigi Vinciguerra.

Or purchase a paid subscription.
© 2026 The Web Scraping Club SRL · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture