By Rajesh Kannan, Co-Founder & CTO, Gramosoft · Last updated: · Lab results from our own local test on November 3, 2026 (Python 3.13, httpx 0.28, parsel)

Your scraper runs against an airline, bank or retail site, every request returns HTTP 200, and the database fills with pages that hold nothing. That's often Imperva, the protection formerly known as Incapsula. This guide shows how to recognise it, tell its block pages from real ones, check pages the right way, and choose a route that holds up, including GcrawlAI.

TL;DR

  • Recognise it: visid_incap_ and incap_ses_ cookies, an X-Iinfo header and scripts from /_Incapsula_Resource. Real pages carry them too.
  • Four shapes: a terminal block, a "Pardon Our Interruption" interstitial, a thin page and the served page. Most refusals return HTTP 200.
  • Common checks fail: in our lab, status != 200 caught 2 of 20 refusals, and a cookie check flagged every real page.
  • Check the field you need: "fewer than 5 priced products" caught all 20 refusals with no false alarms.
  • Pick a route you're allowed to use: an official API or permission first; for public pages you may collect, GcrawlAI renders them in a real browser.

How do you scrape an Imperva-protected website? First confirm it's Imperva from its visid_incap_, incap_ses_ and X-Iinfo signals. Then stop trusting status codes: Imperva's block pages usually come back as 200. Use an official API or ask for access where you can; for public pages you're allowed to collect, fetch them through a real browser, for example with GcrawlAI, and keep a page only if the field you need is in it.

Three routes to the same data

Route Best when Trade-off
Official API, feed or data licence The site offers one, or will on request Paperwork, sometimes a fee, but nothing to keep unblocking
Managed browser API Public pages you're allowed to collect, at volume A cost per page, and you still validate fields
Your own browser automation Small, occasional jobs on sites that allow it You own the browsers, IPs, failures and upkeep

Protected pages, one request each: GcrawlAI

Imperva serves its pages to clients that look like a real browser from a trustworthy IP, browsing at a human pace. Building that yourself means running browsers, proxies and retry logic, and keeping them current. GcrawlAI does it inside one API request and returns the rendered page, so your Python code only has to check that the fields are there.

GcrawlAI homepage with the logo and menu (Products, Playground, Extractors, Docs, Pricing, Blog, Use Cases, Custom Request): Transform any website into structured LLM-ready data, the open-source web scraping API for AI agents, RAG pipelines and data teams, with JavaScript rendering, anti-bot stealth and proxies included in every request and no credit system; General, Extractors and Offline Bundle modes, tabs for Scrape, Map, Crawl, Batch, Screenshot, Search and Smart Answer, and the Batch tab open with a URL list, Markdown format, country picker and a Start batch scraping button
The GcrawlAI homepage doubles as a playground: here the Batch tab queues a list of URLs as one job, with rendering, anti-bot stealth and proxies included in every request (desktop screenshot taken October 31, 2026; the phone view, from October 28, shows on small screens).

The homepage says it plainly: JavaScript rendering, anti-bot stealth and proxies are included in every request, with no credit system. That matters on Imperva sites, where every page needs a real browser and a residential IP, so a premium option charged at a multiple of a basic request would be on every call.

Circuit-board diagram, one protected page, one request, what happens inside a GcrawlAI scrape: U1 your request, URL and country in one API call; U2 a real browser runs the page's JavaScript and keeps cookies; U3 a residential IP in the country you chose; U4 retries and stealth escalation inside the same request; U5 HTML and Markdown out, and your code checks the shape; a request that succeeds is billed as 1 request, a failed request is never charged
One protected page, one request: the browser, IP and retries sit inside a single call.

Here's the client. It asks GcrawlAI for the page and keeps it only if it's the served shape, using the same classifier shown later in this guide:

# pip install gcrawl-sdk parsel
"""Fetch a public page you're allowed to collect through GcrawlAI, then keep it only if
it's the served shape: not a terminal block, an interstitial or a thin shell."""
import os
import time

from gcrawl_sdk import GcrawlClient, ScrapeOptions
from gcrawl_sdk.exceptions import GcrawlAPIError, GcrawlTimeoutError

from classify_imperva import response_shape

gc = GcrawlClient(api_key=os.getenv("GCRAWL_API_KEY", "gc-YOUR_API_KEY"))
OPTS = ScrapeOptions(html_enabled=True, html_clean=False, markdown_enabled=True, proxy_geo="GB", timeout=60)


def fetch(url: str, item_css: str, tries: int = 3):
    for attempt in range(1, tries + 1):
        try:
            page = gc.scrape(url=url, options=OPTS, wait=True)
            shape = response_shape(page.html or "", item_css)
            if shape == "served":
                return page
            print(f"attempt {attempt}: got the {shape} shape")
        except (GcrawlAPIError, GcrawlTimeoutError) as e:
            print(f"attempt {attempt}: {e}")
        time.sleep(2 ** attempt)                     # back off; never hammer a protected host
    return None


if __name__ == "__main__":
    page = fetch("https://example.co.uk/kitchen/kettles", item_css="li.product")
    print(page.markdown[:500] if page else "no usable page")
  • Rendering and access: a real browser through residential IPs in the country you choose, with retries and stealth escalation inside the request.
  • Output you can check: HTML, Markdown or JSON, plus extractors that return structured fields for common page types.
  • Scrape, crawl, screenshots and Search API: scrape single pages, crawl whole sites, capture screenshots, or use the Search API.
  • For developers and AI agents: a Python SDK, an MCP server for Claude, Cursor and other agents, the Playground to test a page before you write code, and the docs.

The MIT-licensed core also runs on your own servers: clone it from GitHub, install the Python requirements, and run the API with Redis and a Celery worker. The setup script is in the code download.

Pricing is a free plan of 50 requests a month with no card, paid plans from $0.67 to $1.45 per 1,000 requests, and a self-hosted core that costs nothing. Failed requests are never charged. The full plan table is in the cost section.

Where it falls short: no service clears every Imperva deployment every time, GcrawlAI included, and there's no public Imperva benchmark to point to yet, so test your own targets on the free plan. It won't log in for you, and it doesn't make collecting a site's data acceptable when that site's terms say no.

"On Imperva sites the status code is almost useless. We've seen runs report 100% success while storing block pages. Every page we keep has to hold the field we came for."

Rajesh Kannan, Co-Founder & CTO at Gramosoft

What Imperva (Incapsula) is

Imperva is a CDN, web application firewall and bot-protection service that sits in front of a website and inspects every request before the site sees it. It began as Incapsula, which is why its cookies and block pages still carry that name, and it's now part of Thales. It's common on banks, airlines, government and large retail sites.

Two layers matter for scraping. The firewall applies rules and stamps responses with an X-Iinfo header. Advanced Bot Protection runs JavaScript in the browser, collects a device fingerprint, and issues a reese84 token that later requests must carry. Scrapeway notes that a request without a valid, unexpired reese84 is blocked on sites that use it, and older deployments use a ___utmvc cookie instead.

Like other bot-management systems, Imperva scores several things together: the network handshake, IP reputation, request headers, the JavaScript check and behaviour over a session. Decodo and ZenRows describe the same layers. For scraping, the point is simple: a plain HTTP client can't run the JavaScript check, so on sites that use it, it never gets the page.

How to tell a site uses Imperva

Imperva is easy to recognise, because it leaves its name on cookies, headers and script paths. The catch is that those signals appear on real pages as well as blocks. Scrapfly found the same X-Iinfo header and incap_ses cookie on imperva.com's real homepage. They tell you who's in front of the site, not whether you were let through.

Signal What it looks like On real pages too?
Visitor and session cookies visid_incap_<site id>, incap_ses_<n>_<site id>, nlbi_ Yes
JavaScript-check cookies reese84 or ___utmvc, set after the script runs in a browser Yes
Response headers X-Iinfo, sometimes X-CDN: Imperva Yes
Script path /_Incapsula_Resource?… on the site's own domain Sometimes
Block text "Request unsuccessful. Incapsula incident ID", "Pardon Our Interruption" No

This classifier reports the signals and names the response shape. It needs only httpx and parsel:

# pip install httpx parsel
"""Is this site behind Imperva, and which of the four response shapes did you get?"""
import re
import sys

import httpx
from parsel import Selector


def imperva_signals(r: httpx.Response) -> list[str]:
    found = []
    names = [c.split("=", 1)[0] for c in r.headers.get_list("set-cookie")]
    for prefix in ("visid_incap_", "incap_ses_", "nlbi_", "reese84", "___utmvc"):
        if any(n.startswith(prefix) for n in names):
            found.append("cookie " + prefix)
    if "x-iinfo" in r.headers:
        found.append("header X-Iinfo")
    if "imperva" in r.headers.get("x-cdn", "").lower() or "incapsula" in r.headers.get("x-cdn", "").lower():
        found.append("header X-CDN: " + r.headers["x-cdn"])
    if "/_Incapsula_Resource" in r.text:
        found.append("script /_Incapsula_Resource")
    return found


def response_shape(html: str, item_css: str = "li.product", min_items: int = 5) -> str:
    if "Incapsula incident ID" in html:
        return "terminal block"
    if "Pardon Our Interruption" in html or "interstitial-inprogress" in html:
        return "interstitial"
    sel = Selector(html)
    if len(sel.css(item_css)) >= min_items:
        return "served"
    return "thin" if sel.css("title::text").get() else "unknown"


if __name__ == "__main__":
    url = sys.argv[1] if len(sys.argv) > 1 else "http://127.0.0.1:8773/p/1"
    r = httpx.get(url, headers={"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
                                              "(KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"})
    print(f"{r.status_code}  {len(r.content):,} bytes  {url}")
    for s in imperva_signals(r):
        print("  -", s)
    print("shape:", response_shape(r.text))

Against our lab edge, which copies Imperva's public response shapes, every response carried the same three cookies, X-Iinfo and X-CDN, the served page included. Only the shape told a block from the real page.

The four shapes an Imperva response takes

An Imperva response arrives in one of four shapes, and only one of them is the page you wanted. ScrapeBadger's captures across eight hosts found every Imperva refusal came back as HTTP 200, so the shape, not the status, tells you what happened and what to do next.

Naturalist field-guide cards, four Imperva response shapes: No. 1 terminal block, about 1 KB, one iframe reading Request unsuccessful. Incapsula incident ID, usually 200 and sometimes 403, stop and change route; No. 2 interstitial, Pardon Our Interruption with the title hidden in noscript, a 10-second timer and an _Incapsula_Resource script, 200, needs a real browser; No. 3 thin page, real title and menu but content drawn later by JavaScript, 200, render then re-check the field; No. 4 served page, your fields present with the same Imperva cookies and X-Iinfo header as a block, 200, keep it and alert if the item count drops
Four shapes an Imperva response can take; three of them usually arrive as HTTP 200.
  • Terminal block: about 1 KB, a single iframe whose fallback text reads "Request unsuccessful. Incapsula incident ID". The request was refused; there's nothing to complete.
  • Interstitial: the Advanced Bot Protection page, "Pardon Our Interruption". Its title sits inside <noscript> and the message appears after a 10-second timer, so a rendered scrape can read an empty title.
  • Thin page: the real title and menu, but the content is drawn later by JavaScript. Nothing in it says "blocked".
  • Served page: your fields are present.

A thin page isn't always a block: a single-page app fetched without JavaScript looks the same. Either way the result is the same for your pipeline: no data, so it mustn't be stored as if it were.

Which "am I blocked?" checks work

Most scrapers decide success with one quick test: the status code, a cookie, a block phrase or the page size. We scored six common checks against 40 lab responses with a known answer: 20 real pages and 20 refusals or empty pages, 18 of them HTTP 200. Only one check caught every refusal without a false alarm.

Dot-strip chart from our November 3, 2026 local lab, 40 responses from a toy edge with 20 refusals and 20 real pages: status != 200 caught 2 of 20 with 0 false alarms; Imperva cookie present caught 20 but flagged all 20 real pages; incident ID in body caught 10; Pardon Our Interruption caught 6; HTML under 10 KB caught 20 with 9 false alarms; fewer than 5 priced items caught 20 with 0 false alarms
Our lab: only the field check caught every refusal without flagging a real page.

The scoring script and the lab edge are in the code download, so you can rerun the test or point it at your own saved responses.

The status code caught only the two 403s. The cookie check flagged everything, because Imperva sets its cookies on real pages too. Each block phrase caught only its own shape, and the size check flagged 9 short but real pages. ScrapeBadger saw the same on live captures: no single published check caught more than 5 of their 7 refusals.

  • Validate on the field you need: a price, an item count, a listing ID. Zero prices is a failure whatever the status.
  • Use the block phrases for logging, not for success: they tell you which shape you got, which tells you what to change.
  • Alert on the field rate: a drop in items per page is your first sign of trouble.

"The checks people copy from forum posts each catch one shape. Asking whether the page holds the field you came for catches all of them, and it's three lines of code."

Rajesh Kannan, Co-Founder & CTO at Gramosoft

Pace requests, back off and stop

Imperva watches behaviour over a session, and blocked IPs don't always stay blocked: Scrapfly reported a blocked IP getting the real homepage again the next morning. Both point the same way. Slow, polite collection fails less, and hammering a block only makes it longer.

  • Start slow and raise the rate only while your field rate stays flat.
  • Back off on any refusal shape, not just 403 and 429, and wait longer after each one.
  • Cap concurrency per site and honour robots.txt, including any crawl delay.
  • Stop on a terminal block: retrying the same request the same way won't change the answer.

We don't cover forging or replaying reese84 tokens, malformed-cookie tricks, or patching browsers to hide automation. They defeat a control the site chose to deploy, they break with each Imperva update, and they carry the most legal risk.

How to judge a scraping API on Imperva

There's no independent Imperva success-rate benchmark to lean on yet. Scrapeway's Imperva page, updated October 27, 2026, says none of its monthly targets sits behind Imperva, so it publishes no ranking. Any provider's claim, including ours, is something to test on your own pages before you commit.

  • Test on your real URLs, not the provider's demo targets, over a few days rather than one run.
  • Score on fields, not status: count pages that hold the data you need.
  • Compare cost per usable page: a cheap request that returns a terminal block isn't cheap.
  • Check what's billed: some providers charge for every 200, even when it's a block page.

What scraping protected pages costs

Imperva sites need JavaScript rendering and usually premium IPs on every page, so compare providers on their protected-page price, not their headline rate. For 100,000 successful protected pages a month, credit-based APIs cost $249 to $399 at list price and GcrawlAI costs $101. For plain pages, they're cheaper.

Option, 100,000 successful pages a month Plain HTML pages Protected pages (JS rendering + premium proxies) Are failed requests billed?
GcrawlAI (every request rendered, residential IPs included) $101 (Growth $79 + 20,000 overage at $1.10 per 1,000) $101 (same request, no multiplier) No: failed requests are never charged
ScraperAPI $49 (Hobby, 100,000 credits) $299 (Business; 25 credits per page = 2.5M credits) Charges only 200 and 404 responses
ZenRows $39 (Build B3, 120,000 credits) $399 (Growth G3; 25 credits per page = 2.5M credits) Failed requests never charged; 404 and 410 count as successful
ScrapingBee $49 (Freelance, 250,000 credits; JS off) $249 (Business; 25 credits per page = 2.5M credits) Charges only 200, 404 and 410

List-price arithmetic, not a benchmark. Credit costs and billing rules come from ScraperAPI's credit docs, ZenRows' pricing docs and ScrapingBee's FAQ, checked November 1, 2026. The honest read: for plain HTML, ZenRows, ScraperAPI and ScrapingBee cost less than GcrawlAI. And on Imperva, billing that counts any 200 as success can include block pages, so the price that matters is per page with your fields in it.

GcrawlAI plans (GcrawlAI pricing, checked October 28, 2026):

Plan Price Requests/month Concurrent Per 1,000 Overage per 1,000
Free $0 forever, no card 50 2 – –
Starter $29/month 20,000 10 $1.45 $1.60
Growth (most popular) $79/month 80,000 35 $0.99 $1.10
Pro $199/month 250,000 50 $0.80 $0.90
Scale $499/month 750,000 100 $0.67 $0.75
Enterprise Volume pricing 2M+ Custom – –
Self-hosted $0 (MIT) Your servers Your servers Infrastructure only –

Every plan, Free included, has scrape, crawl, the Search API, JavaScript rendering, residential IP rotation and stealth escalation in each request, and each feature counts as one request. Failed requests are never charged. Annual billing charges 10 months for 12, unused requests on paid plans roll over once, and Indian customers are billed in INR with a GST invoice.

Which route fits your project

Start with the route that carries the least risk and upkeep, and move on only when it can't give you the data. For Imperva sites that order is usually an official source, then a managed browser API, then browsers you run yourself. The table shows where GcrawlAI fits in each case.

Your situation Route Where GcrawlAI fits
The site has an API, feed or partner programme Use it Not needed; use GcrawlAI for your other, unprotected sources
Public pages, terms allow collection, steady volume Managed browser API with field checks GcrawlAI renders each page in a real browser, one request per page
A handful of pages, occasionally Manual, or a slow, polite browser script The GcrawlAI free plan's 50 requests a month
Not sure it's Imperva, or which shape you get Run the classifier first Fetch the same URL in the GcrawlAI Playground and compare shapes
You need full control of the stack Self-host The MIT GcrawlAI core on your servers
AI agents need the page A tool the agent can call GcrawlAI MCP server with scrape, crawl and Search API

When your own Python is enough

A lot of Imperva-related work needs no service: finding which of your targets use it, classifying the responses you already get, and alerting when the field rate drops. The classifier and field check above cost nothing and belong in every pipeline that touches protected pages, whatever does the fetching.

When volume grows or your field rate falls, move the fetching to GcrawlAI and keep your checks. Its free Cloud plan's 50 requests a month are enough to test your real targets, the Playground shows the result without code, and the MIT core self-hosts for free. For the build-or-buy trade-off, read web scraping with Python vs a scraping API.

Is it OK to scrape an Imperva-protected site?

A site that runs Imperva's bot protection is telling you it filters automated traffic. That doesn't make every collection unlawful, but it raises the bar. Read the terms and robots.txt, ask for an API or data licence, stay on public pages, and keep your pace gentle.

Don't defeat the protection itself: no reverse-engineering its scripts, forging or replaying tokens, or exploiting parser bugs. Imperva often guards logins, checkouts and account flows; leave those alone, and don't collect personal data you have no basis to hold. For the legal background, read what web scraping is and where it's legal, and get advice for your own case.

"Banks and airlines put Imperva in front of their sites for good reasons. When customers bring us one, we start by asking for the feed or the partner API. The pages we do fetch are public ones, at a pace the site won't notice."

Rajesh Kannan, Co-Founder & CTO at Gramosoft

Frequently asked questions

How do I know if a website uses Imperva?

Look for visid_incap_ and incap_ses_ cookies, an X-Iinfo response header, sometimes X-CDN: Imperva, and scripts from /_Incapsula_Resource. These appear on real pages too, so they tell you the site uses Imperva, not that you were blocked.

What does "Request unsuccessful. Incapsula incident ID" mean?

It's the text of Imperva's terminal block page: about 1 KB, with a single iframe. The request was refused outright. It often comes back as HTTP 200, so check the body rather than the status code, and change your route rather than retrying.

What is the "Pardon Our Interruption" page?

The interstitial from Imperva's Advanced Bot Protection: a challenge page whose script has to run in a real browser. Its title sits inside a <noscript> tag and the visible message appears after a 10-second timer.

Why does my Imperva scraper get 200 but no data?

Because most Imperva refusals return HTTP 200: a terminal block, an interstitial or a thin page. In our lab, a status check caught 2 of 20 refusals. Validate on the field you need, such as prices or an item count, before you store the page.

What is the reese84 cookie?

The token Imperva's Advanced Bot Protection sets after its JavaScript check runs in a browser. On sites that use it, requests without a valid, unexpired reese84 are blocked. Older deployments use a ___utmvc cookie for the same job.

Which scraping API works best on Imperva?

There's no independent benchmark yet: Scrapeway's Imperva page, updated October 27, 2026, has no measured ranking. Test providers on your own URLs over several days, count pages that hold your fields, and compare cost per usable page.

Is GcrawlAI open source, and can I use it commercially?

Yes. The GcrawlAI core is MIT licensed on GitHub, so you can self-host it and use it commercially. The managed Cloud API adds residential IPs and stealth escalation, with a Python SDK and MCP for AI agents, a free plan of 50 requests a month and paid plans from $0.67 to $1.45 per 1,000 requests.

RK

Rajesh Kannan M

Rajesh Kannan M is Co-Founder & CTO of Gramosoft in Chennai, where he leads the team building GcrawlAI, an open-source web scraping, crawling and Search API platform for developers and AI agents. LinkedIn

A 200 from Imperva isn't always a page

Start with 50 free requests a month, no card. Send the protected pages you're allowed to collect through GcrawlAI, verify the content that comes back, and pay only for requests that succeed.

CTA Illustration