PrivCaptcha.com

Anti-scraping protection for catalogue and pricing pages

Scraping reads your catalogue at a rate and coverage no reader produces: every SKU, every price, once a day.

How a scraping run works

A scraper walks your pagination and calls search and filter endpoints with generated query strings. Cheap ones are a Scrapy spider on cloud hosts, expensive ones headless Chrome through residential proxies.

What scraping looks like in your logs
Page 40 gets about as many hits as page 2.
Search and export endpoints hit more than the pages linking to them.
Clients that fetch HTML or JSON and never an image or stylesheet.

How PrivCaptcha stops scraping

Four steps, with the numbers the server uses. Nothing here is configured by you.

The header set prices the first page

Scoring starts at 20. A matched crawler user-agent adds 40, Accept-Language 15. 20 + 40 + 15 = 75: level 4.

Level 4 tolerances on every page

Level 4, and the client cannot lower it. 10 shapes, 6 pixels, 10 degrees. Proof-of-work rises to 18 bits: 16 times the hashing.

Careful crawlers start at the floor

Real Chrome headers start at 20, level 2. Failures add 8 points each, capped at 40. A fresh proxy IP resets it.

One token, one response

One token per challenge, and it buys one result set, not the run. Solve caps at 10 requests per second per IP.

What a scraping run costs now: At 18 bits each page costs about 262,000 SHA-256 attempts, and it does not amortise. A 500,000-page catalogue is roughly 10^11 hashes, a few CPU-hours and far more in a browser. Scraping needs all of it, not 90%.

Add PrivCaptcha to your search or export endpoint in two lines of code

Script tag, container in front of the submit button, and your existing verify call. Already on reCAPTCHA or hCaptcha? That backend code stays exactly as it is.

reCAPTCHA siteverify hCaptcha siteverify
Server SDKs
<!-- search or export endpoint -->
<script src="https://privcaptcha.com/1/api.js" async defer></script>
<div class="privcaptcha" data-sitekey="your-site-key"></div>
<!-- server side, unchanged -->
POST https://privcaptcha.com/api/v1/siteverify
Where it goes

On routes a scraper cannot avoid but readers touch rarely: search submit, export. Not catalogue pages.

What the backend does

Verify the token server-to-server at /api/v1/siteverify before the query. Decide how many rows one token buys.

The usual mistake

Mistake: gating the render, not the response. The rows are already in the HTML. Serialise only after verify succeeds.

What this does not solve about scraping

Captchas do nothing for pages not behind them, or against a solve farm. A proxy pool keeps the score near the floor.

Common questions about scraping

How PrivCaptcha prices scraping, and what it does not do about it.

No - put it on search, filter and export. Those are the routes a scraper needs and a reader touches occasionally, and challenging every page view would punish the readers you want.
Going faster costs more, not less. The puzzle and the proof-of-work are per request and there is no cached pass to reuse, so throughput is exactly what the design charges for.
Every request is challenged - there is no invisible pass to aim a script at, and no allowlist that skips the check. What changes is the form the challenge takes and what it costs. The server scores each request and picks one of five difficulty levels, so an ordinary visitor gets a couple of seconds and a client that looks automated gets tight tolerances and a heavier proof-of-work. On the non-visual path, taken by screen-reader and keyboard visitors, there is no puzzle to solve at all: the proof-of-work is the whole challenge, at a fixed 22 bits.
No. An address is used for the length of one request and never written anywhere. What we keep is an HMAC of it under a salt that is random, lives only in Redis and rotates every day, so yesterday's hashes cannot be linked to today's. The counters under that hash expire after 24 hours.

Put PrivCaptcha in front of your search or export endpoint

10,000 verifications a month are free, and the integration is the one you already have.