Refer a friend: you earn 15% of every order, they get 10% off
HomeGlossaryHTTP/2 Fingerprint
Glossary

HTTP/2 Fingerprint

A signature built from how a client opens an HTTP/2 connection: its settings, window sizes, priorities and header order.

When a client opens an HTTP/2 connection it announces a set of parameters before any request is made: frame settings, an initial window size, priority information and the order in which pseudo-headers appear. Those choices are made by the library rather than by you, and different libraries make them differently.

The result is a signature that identifies the tool. A popular scraping library, a browser engine and a command line client each produce a recognisably different one, and the difference is visible before the first request line is read.

This is why a refusal that arrives instantly, on every address you try, often has nothing to do with addresses. The client announced what it was during connection setup, and the decision was made there.

It is also why the fix lives in the client. Matching a browser means using a client that negotiates like one, not sending a browser user agent from a library that negotiates like a library. A convincing user agent on a mismatched connection is a contradiction the server sees immediately.

What is announced before the request

The connection opens with a settings frame: header table size, whether push is enabled, maximum concurrent streams, initial window size and frame size. Libraries pick different values and send them in different orders.

Pseudo-header order follows. The four required pseudo-headers can be sent in any order and each implementation has its habit, which alone narrows the field considerably.

Together with the TLS handshake that preceded it, this gives a defence two independent signatures before it has seen a single ordinary header, and both are properties of the software rather than of the network.

Telling a client problem from an address problem

One experiment separates the two, and it takes a minute:

Same address, different clients

# same exit, two different clients
curl -o /dev/null -s -w "curl: %{http_code}
" -x login_c_US:password@proxy.sotaproxy.com:10000 https://target.example/

# then the same URL through a real browser using the same exit
# if curl is refused and the browser is not, the address was never the problem
  • If every address class is refused instantly, suspect the client before buying a more expensive address.
  • A browser user agent sent from an HTTP library is worse than no user agent at all: it creates a contradiction that is trivial to detect.
  • Where a site genuinely requires browser-grade negotiation, the answer is a browser, and the cost of that is traffic rather than address type.

What it is not

It is not the same as JA3

JA3 describes the TLS handshake. This describes the HTTP/2 layer above it. A site can check either or both.

A proxy does not change it

The signature belongs to your client. Routing it through a different country changes where it arrives from, not what it looks like.

It is not defeated by headers

Header values are read after the connection is already characterised. Changing them cannot undo the impression.

It is not always being checked

Plenty of sites never look. The way to find out is the two-client experiment rather than assumption.

Ready to use http/2 fingerprint?

SotaProxy gives you access to rotating residential, mobile, datacenter, and ISP proxies. No minimum commitment.

Get started