SkillAgentSearch skills...

http2-header-impersonation

Spoof HTTP/2 SETTINGS frames and pseudo-header order per browser profile.

Install / Use

npx skills add uphiago/recon-skills --skill http2-header-impersonation

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

89/100

Supported Platforms

Universal

Our assessment of http2-header-impersonation

http2-header-impersonation scores 89/100 on our quality scale, 1197th of 4,259 Development & Engineering skills we index (top 29%).

Its SKILL.md is 9.4 KB long, well organised into 36 sections with 8 code examples: a thorough specification that gives an agent plenty to work with.

With 1,280 GitHub stars, it is one of the more widely adopted skills in the catalogue.

Substance
29/30
Structure
20/20
Description
12/15
Adoption
13/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 29 days ago, so http2-header-impersonation is actively maintained.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

http2-header-impersonation compared with similar skills

All 4 of these similar skills score higher than http2-header-impersonation; compare them before choosing.

SkillScoreStarsUpdatedFormat
http2-header-impersonation (this skill)by uphiago891.3k29d agoSKILL.md
Agent-Reachby Panniantong10086.6k15d agoCLAUDE.md
headroomby headroomlabs-ai10074.2ktodayCLAUDE.md
ai-job-searchby MadsLorentzen10044.6k1d agoCLAUDE.md
claude-howtoby luongnv8910041.7ktodayCLAUDE.md

Frequently asked questions

How do I install http2-header-impersonation?
Run npx skills add uphiago/recon-skills --skill http2-header-impersonation. The install tabs above show the steps for each supported agent.
Which AI agents does http2-header-impersonation work with?
It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
Is http2-header-impersonation safe to use?
It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is http2-header-impersonation still maintained?
The repository was last updated 29 days ago, so http2-header-impersonation is actively maintained.

name: http2-header-impersonation description: Spoof HTTP/2 SETTINGS frames and pseudo-header order per browser profile. version: 1.1.0 revision_date: 2026-07-25 license: MIT platforms: [linux] compatibility: Requires curl, httpx, python3 tags: [recon, HTTP2, headers, fingerprint, impersonation, browser, JA4] category: recon related_skills:

  • tls-fingerprint-impersonation
  • stealth-browser-launch

HTTP/2 Header Impersonation

Spoof HTTP/2 SETTINGS frames, pseudo-header ordering, and browser-specific HTTP headers to match real browsers at the protocol level. Targets the detection gap between TLS fingerprinting (ClientHello) and JavaScript fingerprinting — the HTTP/2 connection setup and header structure that anti-bot systems analyze. Matches Chrome, Firefox, Safari iOS, and OkHttp (Android) profiles with exact window sizes, header list limits, and header ordering.

When to Use

  • TLS fingerprint is correct but target still detects non-browser HTTP behavior.
  • Target uses HTTP/2-specific detection (SETTINGS frame analysis, pseudo-header order).
  • Need browser-accurate sec-ch-ua, Accept, Accept-Encoding, Priority, and sec-fetch-* headers.
  • Mobile API endpoints require Android OkHttp header profiles.
  • Combining with TLS impersonation for a complete network-level browser profile.

Prerequisites

  • terminal with python3.
  • pip install impit (includes HTTP/2 impersonation via patched h2 library).
  • Or standalone: use the header lists below to configure curl/httpx manually.

Quick Detection

# Check if target sends different responses based on HTTP headers
# Compare browser-like headers vs curl defaults

python3 -c "
import requests

# curl default headers
r1 = requests.get('https://target.com')
print(f'Default: {r1.status_code}')

# Browser-like headers
r2 = requests.get('https://target.com', headers={
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/[REDACTED_IP] Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.9',
    'Accept-Encoding': 'gzip, deflate, br, zstd',
    'sec-ch-ua': '\"Chromium\";v=\"142\", \"Google Chrome\";v=\"142\"',
    'sec-ch-ua-platform': '\"Windows\"',
    'sec-ch-ua-mobile': '?0',
})
print(f'Browser: {r2.status_code}')
"

Procedure

Phase 1 — Full Browser Profile via impit

The impit library applies HTTP/2 SETTINGS, pseudo-header order, and HTTP headers from a single profile:

from impit import Impit

# Chrome 142 — complete HTTP/2 + TLS + headers profile
impit = (
    Impit.builder()
    .with_fingerprint("chrome142")
    .build()
)

response = impit.get("https://target.com")
# Headers sent: sec-ch-ua, User-Agent, Accept, Accept-Encoding, Accept-Language,
#              sec-ch-ua-platform, sec-ch-ua-mobile, Priority, sec-fetch-*
# HTTP/2 SETTINGS: stream_window=6291456, conn_window=15663105, max_header=262144
# Pseudo-header order: :method :authority :scheme :path :protocol :status

Phase 2 — Manual Header Configuration

For curl/httpx without impit, configure headers manually to match browser profiles:

Chrome 142 Desktop Headers

curl --max-time 30 --connect-timeout 10 -sk "https://target.com" \
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/[REDACTED_IP] Safari/537.36" \
  -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" \
  -H "Accept-Language: en-US,en;q=0.9" \
  -H "Accept-Encoding: gzip, deflate, br, zstd" \
  -H "sec-ch-ua: \"Chromium\";v=\"142\", \"Google Chrome\";v=\"142\", \"Not?A_Brand\";v=\"99\"" \
  -H "sec-ch-ua-arch: \"x86\"" \
  -H "sec-ch-ua-bitness: \"64\"" \
  -H "sec-ch-ua-full-version-list: \"Chromium\";v=\"142.0.7444.176\", \"Google Chrome\";v=\"142.0.7444.176\", \"Not?A_Brand\";v=\"[REDACTED_IP]\"" \
  -H "sec-ch-ua-mobile: ?0" \
  -H "sec-ch-ua-model: \"\"" \
  -H "sec-ch-ua-platform: \"Windows\"" \
  -H "sec-ch-ua-platform-version: \"15.0.0\"" \
  -H "sec-ch-ua-wow64: ?0" \
  -H "sec-fetch-dest: document" \
  -H "sec-fetch-mode: navigate" \
  -H "sec-fetch-site: none" \
  -H "sec-fetch-user: ?1" \
  -H "Upgrade-Insecure-Requests: 1" \
  -H "Priority: u=0, i"

Firefox 144 Desktop Headers

curl --max-time 30 --connect-timeout 10 -sk "https://target.com" \
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:144.0) Gecko/20100101 Firefox/144.0" \
  -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8" \
  -H "Accept-Language: en-US,en;q=0.5" \
  -H "Accept-Encoding: gzip, deflate, br, zstd" \
  -H "sec-ch-ua: \"Firefox\";v=\"144\", \"Not?A_Brand\";v=\"99\"" \
  -H "sec-ch-ua-mobile: ?0" \
  -H "sec-ch-ua-platform: \"Windows\"" \
  -H "sec-fetch-dest: document" \
  -H "sec-fetch-mode: navigate" \
  -H "sec-fetch-site: none" \
  -H "sec-fetch-user: ?1" \
  -H "TE: trailers" \
  -H "Upgrade-Insecure-Requests: 1" \
  -H "Priority: u=0, i"

Safari iOS 18 Headers

curl --max-time 30 --connect-timeout 10 -sk "https://target.com" \
  -H "User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.7 Mobile/15E148 Safari/604.1" \
  -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" \
  -H "Accept-Language: en-US,en;q=0.9" \
  -H "Accept-Encoding: gzip, deflate, br" \
  -H "sec-fetch-dest: document" \
  -H "sec-fetch-mode: navigate" \
  -H "sec-fetch-site: none"

OkHttp 4 (Android) Headers

curl --max-time 30 --connect-timeout 10 -sk "https://target.com" \
  -H "User-Agent: okhttp/4.12.0" \
  -H "Accept: application/json, text/plain, */*" \
  -H "Accept-Language: en-US,en;q=0.9" \
  -H "Accept-Encoding: gzip, deflate, br" \
  -H "Connection: Keep-Alive"

Phase 3 — HTTP/2 SETTINGS Frame Spoofing

HTTP/2 SETTINGS frames are sent during connection setup. curl doesn't expose them — use impit or a patched HTTP client:

from impit import Impit

# Chrome HTTP/2 SETTINGS:
#   SETTINGS_MAX_CONCURRENT_STREAMS: 1000
#   SETTINGS_INITIAL_WINDOW_SIZE: 6291456
#   SETTINGS_MAX_HEADER_LIST_SIZE: 262144
# Firefox HTTP/2 SETTINGS:
#   SETTINGS_MAX_CONCURRENT_STREAMS: 125
#   SETTINGS_INITIAL_WINDOW_SIZE: 131072

impit = Impit.builder().with_fingerprint("chrome142").build()
response = impit.get("https://target.com")

Phase 4 — Pseudo-Header Order

Browsers send HTTP/2 pseudo-headers in specific orders. This is enforced at the h2 library level:

| Browser | Pseudo-Header Order | |---|---| | Chrome | :method, :authority, :scheme, :path, :protocol, :status | | Firefox | :method, :path, :authority, :scheme, :protocol, :status | | Safari iOS | :method, :scheme, :authority, :path, :protocol, :status | | OkHttp | :method, :path, :authority, :scheme, :protocol, :status |

Detection: Some reverse proxies inspect pseudo-header order to distinguish browsers. Firefox places :path before :authority — a unique fingerprint. Safari places :scheme second — another differentiator.

Phase 5 — Header Prioritization

Custom headers take priority over fingerprint defaults to avoid conflicts:

impit = Impit.builder().with_fingerprint("chrome142").build()

# Custom headers WIN over fingerprint defaults for same header name
response = impit.get("https://target.com", headers={
    "Authorization": "Bearer custom-token",
    "X-Custom-Header": "value",
})
# Authorization is added; all fingerprint headers still applied for unset names

Phase 6 — Accept-Encoding Strategy

Browser Accept-Encoding values differ significantly:

| Browser | Accept-Encoding | |---|---| | Chrome 142 | gzip, deflate, br, zstd | | Chrome 100-116 | gzip, deflate, br | | Firefox | gzip, deflate, br, zstd | | Safari iOS | gzip, deflate, br | | OkHttp 4 | gzip, deflate, br |

Detection: Some CDNs return different content based on Accept-Encoding (brotli vs zstd capability profiling). Match encoding capabilities to your target browser.

Pitfalls

  • curl cannot spoof HTTP/2 SETTINGS frames. Only use curl-based headers for HTTP/1.1 targets or when TLS fingerprinting is the primary concern, not HTTP/2.
  • Header order matters in HTTP/2. Some detectors check the order of header fields, not just their presence.
  • sec-ch-ua must match User-Agent. Using Chrome headers with Firefox UA creates an inconsistency that detectors flag.
  • sec-ch-ua format is version-specific. Chrome 100+ uses different brand strings than Chrome 124+.
  • Mobile headers without TLS matching is detectable. Using Safari iOS headers over a desktop TLS fingerprint is flagged.
  • Custom headers are deduplicated case-insensitively. Adding User-Agent as custom overrides the fingerprint's User-Agent.

Verification

  1. Test against https://httpbin.org/headers — verify all sent headers match the intended browser profile.
  2. For HTTP/2 SETTINGS verification, use https://nghttp2.org/httpbin/headers or a local nghttp2 server.
  3. Compare response size/content between browser-impostor and real browser — identical responses indicate the headers are accepted.
  4. Check Cloudflare cf-ja4 header — it encodes HTTP/2 fingerprint along with TLS.

Related Skills

  • tls-fingerprint-impersonation — TLS ClientHello and JA3/JA4 fingerprint spoofing.
  • stealth-browser-launch — Full browser automation with C++ fingerprint patches.

Related Skills

View on GitHub
GitHub Stars1.3k
CategoryDevelopment
Updated29d ago
Forks215

Languages

Python

Trust signals

100/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

No cautions