Fingerprints
Many sites decide whether you're a bot before reading a single byte of your request: from the TLS handshake (the JA3/JA4 fingerprint) and the HTTP/2 settings, which differ between a real browser and a scraping library. A browser User-Agent sent over a library's connection is the most obvious bot signal there is.
Every request without a browser looks like it comes from a real browser, with three things that agree with each other. options.fingerprint picks which browser:
- a current User-Agent of that browser, for a realistic platform (Windows, macOS, Linux, Android, iPhone, iPad);
- the headers that browser sends with it:
Accept,Accept-Language,Sec-Fetch-*, and for Chromium theSec-CH-UAclient hints matching the version and platform; - the browser's TLS fingerprint and HTTP/2 connection settings.
"options": { "fingerprint": "chrome" }A fingerprint isn't a browser
The request is still a plain HTTP request: no page is rendered and no JavaScript runs. It only looks like a browser to the site. To render pages in a real browser, use options.browser.
| Value | Effect |
|---|---|
true or absent | Any browser, weighted by real-world usage (default) |
"chrome", "chrome-mobile", "edge", "firefox", "safari", "safari-mobile" | That browser |
["firefox", "safari"] | Any of these |
false | The API's own identity, scraping-engine/0.1 over a standard connection. Many sites block it |
See it work
tls.peet.ws reports the fingerprint it sees. With "fingerprint": false, the JA4 is a scraping library's, over HTTP/1.1, with no HTTP/2 fingerprint at all:
Actions
Data
With "fingerprint": "chrome", the JA4 is Chrome's own, t13d1516h2_8daaf6152771_…, over HTTP/2:
Actions
Data
The response tells you which fingerprint was used:
"fingerprint": { "name": "chrome", "platform": "Windows" }Rotation
The API picks a new fingerprint, among the browsers you allow, for every attempt: platform and device change between retries. Combine it with a proxy to change the address too:
"options": { "fingerprint": true, "proxy": true, "retry": 3 }Always current
Browser versions are refreshed every day from Google's, Mozilla's and Apple's release data, so User-Agents and client hints always name the current stable versions. A User-Agent several versions old is a common bot signal.
Customize headers
Headers you set in options.headers replace the ones the fingerprint would send. For example, send an Accept-Language that matches your proxy's country instead of the default en-US:
"options": {
"fingerprint": "chrome",
"proxy": { "country": "FR" },
"headers": { "Accept-Language": "fr-FR,fr;q=0.9" }
}Avoid replacing the User-Agent: the TLS fingerprint would still be the browser's, and the mismatch is easy to spot.
Fingerprints and proxies
Fingerprints work with HTTP, HTTPS and SOCKS5 proxies. SOCKS4 proxies can't carry them: when fingerprint is set, SOCKS4 entries in your own proxy list are skipped.
Fingerprints and fallbacks
A common pattern: try the fast, plain request first, and use a fingerprint only if the site refuses:
"options": {
"fallback": [{ "fingerprint": "chrome" }]
}"fingerprint": false in a fallback strategy goes back to the plain identity.
Caching
Pages fetched with a fingerprint are cached separately per set of browsers.
Fingerprints and browsers
With options.browser, the browser has its own, real fingerprint. A fingerprint only dresses a plain chromium (with chrome, chrome-mobile or edge) or firefox (with firefox); stealth browsers keep their own, and a warning says so.