An HTTP/2 Fingerprint is a passive identification technique that profiles a client by inspecting the specific parameters and frame sequences it transmits during the initial HTTP/2 connection preface and SETTINGS frame exchange. Unlike HTTP/1.1, where the User-Agent string is easily spoofed, HTTP/2 requires clients to declare capabilities like SETTINGS_MAX_CONCURRENT_STREAMS, SETTINGS_INITIAL_WINDOW_SIZE, and SETTINGS_HEADER_TABLE_SIZE. The exact combination of these values, along with the order of pseudo-headers (:method, :path, :authority) and stream prioritization weights, creates a highly stable identifier that distinguishes a headless Chrome instance from a native browser or a Python httpx client from a legitimate crawler.
Glossary
HTTP/2 Fingerprint

What is HTTP/2 Fingerprint?
A method of identifying clients by analyzing the unique combination of SETTINGS frame values, pseudo-header order, and stream prioritization logic exchanged during an HTTP/2 connection handshake.
This technique is critical for AI crawler identification because autonomous agents and scraping libraries often use default HTTP/2 stacks that deviate from standard browser implementations. For instance, the Go HTTP client used by many scrapers sends a distinct SETTINGS frame order and lacks the WINDOW_UPDATE frame timing characteristic of Chromium-based browsers. Security architects integrate HTTP/2 fingerprinting into edge bot management platforms to passively reject traffic from unverified AI training bots, even when they present convincing User-Agent strings and residential IP addresses, providing a defense layer that operates below the JavaScript execution environment.
Key Characteristics of HTTP/2 Fingerprints
HTTP/2 fingerprinting analyzes the unique, low-level parameters exchanged during the initial connection preface to identify specific client implementations, even when high-level identifiers like the User-Agent string are spoofed.
SETTINGS Frame Analysis
The SETTINGS frame is the cornerstone of HTTP/2 fingerprinting. During the connection preface, the client sends a SETTINGS frame containing a list of key-value pairs that configure the connection. The specific combination of parameters—such as SETTINGS_MAX_CONCURRENT_STREAMS, SETTINGS_INITIAL_WINDOW_SIZE, and SETTINGS_HEADER_TABLE_SIZE—varies significantly between browser engines, language libraries, and crawler implementations. For example, Chrome consistently advertises a maximum concurrent streams value of 1000, while Python's httpx library defaults to 100. These values are not arbitrary; they reflect the internal buffer allocations and concurrency models of each client.
Pseudo-Header Order
HTTP/2 mandates the use of pseudo-headers (:method, :path, :scheme, :authority) that precede regular headers in a request. While the specification requires pseudo-headers to appear before ordinary headers, it does not enforce a strict order among the pseudo-headers themselves. Different implementations serialize them in distinct sequences. For instance, Go's http2 library consistently sends :method, :scheme, :path, :authority, whereas Firefox uses :method, :path, :authority, :scheme. This ordering is a deeply embedded artifact of each client's HTTP/2 frame serializer and is extremely difficult to modify without patching the networking stack.
Stream Prioritization Logic
HTTP/2 introduces a stream prioritization mechanism using a dependency tree and weight system. Clients signal how the server should allocate bandwidth among concurrent streams by sending PRIORITY frames that define parent-child relationships and integer weights (1-256). The structure of this tree is a powerful fingerprinting vector. Chromium-based browsers build a complex, deeply nested prioritization tree to optimize rendering-critical resources, while simpler HTTP clients like curl or Python's requests often send a flat tree or omit PRIORITY frames entirely. The absence of prioritization is itself a strong signal of an automated agent.
HPACK Compression Behavior
HTTP/2 uses HPACK, a specialized compression algorithm for header fields, which relies on a shared dynamic table between client and server. The way a client populates and references this table reveals its implementation. Key fingerprinting signals include the dynamic table size advertised in SETTINGS, the choice of which headers are indexed versus transmitted literally, and the use of Huffman encoding for string literals. Browsers aggressively index common headers like :authority and content-type to maximize compression efficiency, while many lightweight crawler libraries perform minimal indexing, resulting in larger, less optimized header blocks that stand out under inspection.
WINDOW_UPDATE Strategy
Flow control in HTTP/2 is managed through WINDOW_UPDATE frames that govern how much data a receiver is willing to buffer. The timing and size of these updates expose the client's internal buffer management strategy. Browsers typically maintain large connection-level and stream-level windows, sending WINDOW_UPDATE frames proactively to avoid blocking. In contrast, many automated scrapers and bots use minimal window sizes or delay sending updates, creating a distinctive, constrained traffic pattern. This behavior is a direct reflection of the client's memory allocation strategy and is invisible to tools that only inspect static handshake parameters.
Frame Size and Multiplexing Patterns
The maximum frame size a client is willing to receive, declared in the SETTINGS_MAX_FRAME_SIZE parameter, and the actual sizes of frames it transmits are revealing. Browsers typically use the default maximum of 16,384 bytes for outgoing data frames, while some bots use smaller frames to reduce memory overhead. Additionally, the multiplexing behavior—how many streams a client opens concurrently and how it interleaves their frames—provides a behavioral fingerprint. Browsers open multiple streams for parallel resource loading and interleave frames aggressively. Automated crawlers often serialize requests, opening one stream at a time, which produces a distinctly non-browser-like multiplexing signature.
Frequently Asked Questions
Technical answers to common questions about identifying clients through HTTP/2 connection parameters and handshake analysis.
An HTTP/2 fingerprint is a unique identifier derived from the specific combination of SETTINGS frame parameters, pseudo-header order, and stream prioritization logic that a client transmits during the initial connection preface. Unlike HTTP/1.1, where the User-Agent string is the primary identifier, HTTP/2 requires clients to exchange a series of predefined frames before any data flows. The SETTINGS frame contains key-value pairs like SETTINGS_MAX_CONCURRENT_STREAMS, SETTINGS_INITIAL_WINDOW_SIZE, and SETTINGS_HEADER_TABLE_SIZE. Each browser, library, or crawler implementation sets these values differently. For example, Chrome consistently sends SETTINGS_MAX_CONCURRENT_STREAMS as 1000, while Firefox uses 125. Python's httpx library sends SETTINGS_ENABLE_PUSH as 0 by default. By hashing the ordered sequence of these parameters along with the pseudo-header order (:method, :path, :authority, :scheme), a server can generate a stable fingerprint that persists even when the User-Agent string is spoofed. This technique is particularly effective against AI crawlers and headless browsers that use standard HTTP/2 libraries with predictable default configurations.
Enabling Efficiency, Speed & Accuracy
Intelligent Analysis, Decision & Execution
We build AI systems for teams that need search across company data, workflow automation across tools, or AI features inside products and internal software.
Talk to Us
Search across company data
Give teams answers from docs, tickets, runbooks, and product data with sources and permissions.
Useful when people spend too long searching or get different answers from different systems.

Automate internal workflows
Use AI to route work, draft outputs, trigger actions, and keep approvals and logs in place.
Useful when repetitive work moves across multiple tools and teams.

Add AI to products and internal tools
Build assistants, guided actions, or decision support into the software your team or customers already use.
Useful when AI needs to be part of the product, not a separate tool.
Related Terms
HTTP/2 fingerprinting is one component of a broader bot detection stack. These related techniques combine to create a multi-layered identification mesh that is difficult for sophisticated crawlers to evade.
SETTINGS Frame Analysis
The core mechanism of HTTP/2 fingerprinting. During connection initialization, both endpoints exchange SETTINGS frames containing key-value pairs that define communication parameters. Each client implementation—Chrome, Firefox, Python's httpx, Go's net/http—sends a unique combination of:
- SETTINGS_MAX_CONCURRENT_STREAMS: Varies from 100 (Chrome) to 1000+ (some libraries)
- SETTINGS_INITIAL_WINDOW_SIZE: Often 65535 for browsers, but custom in crawlers
- SETTINGS_HEADER_TABLE_SIZE: Reveals HPACK decoder configuration
- SETTINGS_ENABLE_PUSH: Typically 0 in modern clients
The exact order and presence of these parameters form a deterministic signature.
Pseudo-Header Order Fingerprinting
HTTP/2 replaces the HTTP/1.1 request line with pseudo-headers (:method, :path, :scheme, :authority). The HPACK compression context and the order in which these pseudo-headers appear in the first HEADERS frame vary by implementation. Browsers follow a strict, RFC-compliant order, while many HTTP/2 libraries used by crawlers deviate subtly.
- Chrome:
:method,:authority,:scheme,:path - Some Go clients:
:method,:scheme,:path,:authority - Mismatches against known browser profiles immediately flag headless automation
Stream Prioritization Profiling
HTTP/2's stream prioritization tree defines how the client wants the server to allocate bandwidth across concurrent requests. Browsers generate complex, dynamically-weighted dependency trees to optimize page rendering (prioritizing CSS and critical JS). Automated crawlers typically send:
- A flat prioritization tree with all streams at equal weight
- No PRIORITY frames at all (relying on default values)
- Non-standard exclusive flags that real browsers never set
This behavioral gap is a powerful signal for distinguishing AI training bots from legitimate browser traffic.
WINDOW_UPDATE and Flow Control Behavior
HTTP/2 implements per-stream and connection-level flow control through WINDOW_UPDATE frames. The timing and size of these credit increments reveal client-side buffer management. Browsers exhibit bursty, render-driven patterns tied to parsing HTML and discovering sub-resources. Crawlers, optimized for throughput, often:
- Send large, infrequent WINDOW_UPDATE frames
- Maintain consistently full windows without the variability of human-driven browsing
- Fail to respect stream-level backpressure in ways that differ from browser implementations
This is a passive behavioral fingerprint that requires no active probing.
GREASE and Protocol Invariant Testing
GREASE (Generate Random Extensions And Sustain Extensibility) is a technique where clients inject random, undefined values into TLS extensions and HTTP/2 SETTINGS parameters. Browsers like Chrome actively GREASE their connections to prevent server ossification. The presence, absence, and specific pattern of GREASE values in SETTINGS frames is itself a fingerprinting signal:
- Chrome sends GREASE values in specific SETTINGS slots
- Many HTTP/2 libraries and crawlers omit GREASE entirely
- The exact random values used can correlate with browser version ranges

About the author
Prasad Kumkar
CEO & MD, Inference Systems
Prasad Kumkar is the CEO & MD of Inference Systems and writes about AI systems architecture, LLM infrastructure, model serving, evaluation, and production deployment. Over 5+ years, he has worked across computer vision models, L5 autonomous vehicle systems, and LLM research, with a focus on taking complex AI ideas into real-world engineering systems.
His work and writing cover AI systems, large language models, AI agents, multimodal systems, autonomous systems, inference optimization, RAG, evaluation, and production AI engineering.
Partnered with leading AI, data, and software stack.
How We Work
Custom AI workflows for your Business
One-fit-all AI don't work for modern businesses. At Inferensys, we aim to understand your business & custom requirements; which we use to define most efficient agentic workflows, the data, and the tools for your business.
01
Review the use case
We understand the task, the users, and where AI can actually help.
Read more02
Pick the right approach
We define what needs search, automation, or product integration.
Read more03
Build the first useful version
We implement the part that proves the value first.
Read more04
Improve from there
We add the checks and visibility needed to keep it useful.
Read moreThe first call is a practical review of your use case and the right next step.
Talk to Us