Skip to main content

TLS-Chameleon

TLSChameleom

PyPI version CI

TLS-Chameleon is a modern Python HTTP networking stack with pluggable browser-fingerprint backends, structured fingerprint research tooling, diagnostics, and reproducible experiments — behind a simple, requests-like API.

What it IS: an HTTP client · a fingerprint-aware networking toolkit · a diagnostic system · a protocol-research framework.

What it is NOT: a Cloudflare/WAF bypass guarantee · a CAPTCHA solver · an anonymity or stealth product. Detection outcomes depend on many factors outside any client library's control.

🆕 What's New in v3.0.0

  • Pluggable transport architecturecurl, native (primp/rustls) and httpx backends behind one interface, auto-selected (curl → native → httpx) with graceful degradation. curl_cffi is optional, never architectural.
  • Structured fingerprint system — typed models, registry over 48 profiles, validator (rejects impossible/inconsistent configs), explainable similarity scoring, field-level diffing, live capture via TLS echo endpoints.
  • Diagnosticsresponse.trace, inspect_url(), doctor() with check-by-check verdicts; every output automatically redacted.
  • Adaptive engine — bounded/expiring/thread-safe domain memory with explainable selection (client.profile_for(domain)); header-consistency engine; deterministic randomization via random_seed.
  • CLIchameleon get / inspect / doctor / capture / diff / fingerprint / benchmark / version, all major commands with stable --json.
  • Reproducible benchmarks — real local-server harness, stored methodology, no invented numbers.
  • Honest capability reportingclient.capabilities.tls_fingerprint_spoofing, .http3, ... always reflect what the active backend actually does.

🚀 Features

  • Three interchangeable backends
    • curl — curl-impersonate (curl_cffi): full JA3/JA4/H2 fingerprint control
    • native — primp/rustls stack: browser impersonation without libcurl
    • httpx — honest fallback: standard OpenSSL TLS (no JA3 spoofing)
  • 48+ versioned profiles: Chrome, Firefox, Safari, Edge across Windows 10/11, macOS, Linux, iOS, Android — plus a deterministic generative engine (gen://family/os/major/tier/seed)
  • Fingerprint research toolkit: registry · validation · similarity · diff · live capture
  • Diagnostics & doctor: protocol/backend/timing traces, observed-vs-profile comparison, actionable recommendations
  • Adaptive behavior: per-domain profile learning (bounded, expiring, thread-safe, disableable), header casing/order morphing, WAF detection with retry/backoff/rotation
  • Deterministic randomization: same seed ⇒ identical variants, cipher order and jitter — reproducible experiments
  • Resilience: proxy/profile pools, rate limiting, ghost mode, on_retry hooks
  • Magnet module 🧲: emails, tables, forms, JSON-LD, deep extraction of JWTs/API keys; optional AI providers ([ai] extra)

📦 Install

pip install tls-chameleon            # core: works out of the box via httpx
pip install tls-chameleon[curl]      # + curl-impersonate backend (JA3 spoofing)
pip install tls-chameleon[native]    # + primp/rustls backend (JA3 spoofing, no curl)
pip install tls-chameleon[all]       # everything

Backend honesty: without [curl] or [native] you get the httpx fallback — standard OpenSSL TLS, no JA3 spoofing. The active backend and its true capabilities are always inspectable:

from tls_chameleon import TLSSession

client = TLSSession()
print(client.engine)                                  # "curl" | "native" | "httpx"
print(client.capabilities.http3)                      # only if truly available
print(client.capabilities.tls_fingerprint_spoofing)   # False on httpx!

Pluggable architecture

Public API  (TLSSession / AsyncSession — unchanged names since v2)
     │
tls_chameleon.transport.factory      # auto / curl / native / httpx (+ custom)
     │
Transport interface                  # duck-typed sessions, capability reports
 ├─ CurlTransport    ← only module importing curl_cffi
 ├─ PrimpTransport   ← only module importing primp
 └─ HttpxTransport   ← only module importing httpx

Backends are strictly isolated (enforced by tests). Custom backends plug in via tls_chameleon.transport.register_transport.

⚡ Quick Start

from tls_chameleon import TLSSession

with TLSSession(profile="chrome_130_win11") as client:
    r = client.get("https://example.com")
    print(r.status_code, r.text[:80])
    print(client.engine)                 # which backend served this?
    print(client.capabilities.to_dict()) # what can it really do?

Async:

import asyncio
from tls_chameleon import AsyncSession

async def main():
    async with AsyncSession(profile="chrome_130_win11") as session:
        r = await session.get("https://example.com", trace=True)
        print(r.trace.protocol, r.trace.timing_ms)

asyncio.run(main())

CLI:

chameleon inspect https://example.com --json
chameleon doctor https://example.com --echo-endpoint https://tls.peet.ws/api/clean
chameleon capture https://tls.peet.ws/api/all --raw --json
chameleon fingerprint list --browser chrome
chameleon diff capture_a.json capture_b.json

🔬 Fingerprint System

from tls_chameleon import (
    FingerprintRegistry, validate_fingerprint,
    FingerprintSimilarity, diff_fingerprints, capture,
)

reg = FingerprintRegistry()
fp = reg.get("chrome_120_win11")          # lazy lookup over all built-ins

issues = validate_fingerprint(fp)          # structural + provenance checks

result = FingerprintSimilarity().compare(fp, reg.get("firefox_120_win11"))
print(result.total, result.layers)         # explainable, weighted scoring

report = diff_fingerprints(fp, reg.get("firefox_120_win11"))
print(report.to_text())                    # SAME/DIFFERENT per field + score

# Live capture: what does the network ACTUALLY see?
res = capture(session=client.session)      # via TLS echo endpoint
print(res.fingerprint.tls.ja3_hash)        # source="captured", timestamped

Provenance is explicit — every fingerprint is labeled captured, documented or synthetic; synthetic data can never be marked verified (enforced by the validator).

🩺 Diagnostics

from tls_chameleon import inspect_url, doctor

print(inspect_url("https://example.com", client).to_text())

report = doctor("https://example.com",
                echo_endpoint="https://tls.peet.ws/api/clean")
print(report.to_text())
# [ ✓] Connection: h2 response 200 in 76ms
# [ ✓] Backend: backend 'curl' performs real TLS impersonation
# [ ⚠] Fingerprint (JA4): observed JA4 differs from profile ...
# Verdict: WARN

Traces attach to responses on demand — headers always redacted:

r = client.get(url, trace=True)
r.trace.backend / .protocol / .timing_ms / .request_headers

Unobservable fields stay None with an explanatory note — never guessed.

🧠 Adaptive Engine

client = TLSSession(adaptive=True, adaptive_ttl=3600, random_seed=12345)

client.profile_for("example.com")
# {'profile': 'chrome_130_win11', 'reason': 'learned after 3 successful
#  request(s); 12s ago', 'confidence': 0.6, 'last_used': ...}

Domain memory is LRU-bounded, TTL-expiring, thread-safe, stores only domain → profile (never credentials), and explains itself. Same seed + config ⇒ byte-identical fingerprint choices for reproducible runs.

📚 Profiles

Browser Versions OS
Chrome 120–130, android, latest win10/win11/macos/linux/android
Firefox 120–124 win10/win11/macos/linux
Safari iOS 16/17, macOS 13/14 ios/macos
Edge 120, 124 win10/win11
chameleon fingerprint list                # or: list_available_profiles()
chameleon fingerprint show chrome_130_win11 --json
chameleon fingerprint validate my_profile.json

Generative fingerprints for research/fuzzing: TLSSession(profile="gen://chrome/win11/124/balanced/7") — deterministic per seed, always labeled synthetic.

🛠 API Reference (selection)

Parameter Type Default Description
profile str None Profile name (e.g., 'chrome_124_linux')
engine str 'auto' 'curl', 'native', 'httpx'; auto-selects best installed
randomize / randomize_ciphers bool False Variant generation / cipher-order shuffle
random_seed Any None Deterministic randomization seed
adaptive / adaptive_ttl bool / float True / None Domain-memory learning + expiry seconds
http2 / http3 bool None Protocol preferences (backend-dependent)
verify bool True Certificate verification (never disabled silently)
proxies / proxies_pool dict/str/list None Proxy config / rotation pool
rotate_profiles / on_block list / str None / 'rotate' Block recovery: rotate/proxy/both/none
rate_limit float None Max req/sec per domain
ghost_mode bool False Timing jitter + payload padding

Handy members: client.capabilities, client.profile_for(domain), session.get_fingerprint_info(), response.trace, save_cookies/load_cookies/export_session/import_session, plus the Magnet extractors (response.magnet.*) and submit_form().

🖥 CLI

Command Purpose Exit codes
chameleon get URL [--trace] Spoofed request, redacted output 0 ok / 1 error
chameleon inspect URL One-request structured report 0 / 1
chameleon doctor URL Connection/backend/profile/header checks 0 (warn ok) / 1 fail
chameleon capture [URL] Network-observed fingerprint 0 / 1
chameleon diff A.json B.json Field-level fingerprint diff 0 / 1
chameleon fingerprint list|show|validate Registry operations 0 / 1
chameleon benchmark Reproducible local benchmarks 0 / 3*
chameleon version Version info 0

All major commands accept --json with stable, documented schemas. (*3 = feature pending its phase.)

📊 Benchmarks

Real local-server measurements only — methodology and limitations in docs/BENCHMARK_METHODOLOGY.md, a labeled sample run in docs/BENCHMARK_SNAPSHOT.md. Absolute numbers are machine-specific; compare within a single report.

📖 Documentation

Doc Contents
docs/ARCHITECTURE_AUDIT.md v2 audit + v3 migration plan
docs/NATIVE_BACKEND_RESEARCH.md backend candidates, decision record
docs/BENCHMARK_METHODOLOGY.md what the benchmark measures
docs/migration/curl_cffi.md coming from raw curl_cffi
CHANGELOG.md full v3.0.0 change list

🤝 Contributing

Issues and Pull Requests welcome!

🌟 Credits

Built on curl_cffi, primp, and httpx.

☕ Support / Donate

If you found this library useful, buy me a coffee!

zied

📜 License

MIT

🚨 Is this library failing on a specific site?

Please open an issue with the URL! I need test cases to improve the fingerprinting logic.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tls_chameleon-3.1.0.tar.gz (131.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tls_chameleon-3.1.0-py3-none-any.whl (120.5 kB view details)

Uploaded Python 3

File details

Details for the file tls_chameleon-3.1.0.tar.gz.

File metadata

  • Download URL: tls_chameleon-3.1.0.tar.gz
  • Upload date:
  • Size: 131.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.15

File hashes

Hashes for tls_chameleon-3.1.0.tar.gz
Algorithm Hash digest
SHA256 33dcd369dd55188744abe00d88cb900ce1cfe4df9878b3571abed723e401e77e
MD5 853643108ad5bb5c901845423d03839d
BLAKE2b-256 a43e338c04edc51038bfafd6aceaa8bc2c97b63963792edb3241d0b79c5a4ba2

See more details on using hashes here.

File details

Details for the file tls_chameleon-3.1.0-py3-none-any.whl.

File metadata

  • Download URL: tls_chameleon-3.1.0-py3-none-any.whl
  • Upload date:
  • Size: 120.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.15

File hashes

Hashes for tls_chameleon-3.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9ce23a9b41677dca18960b0fb8c830ede42c2a105a86607420eb464b497c2a99
MD5 3a2cf76d765b45c41cd6ca2707519ec2
BLAKE2b-256 fe47a77149c8cefd176b2b9ed243b883c4033eed2154b8096a9cffade88c7ac1

See more details on using hashes here.

Release history Release notifications | RSS feed

3.1.1

2 files

This release

3.1.0 This release

2 files

3.0.1

2 files

3.0.0

2 files

2.2.0

2 files

2.1.1

2 files

2.1.0

2 files

2.0.0

2 files

1.2.0

2 files

1.1.1

2 files

1.1.0

2 files

1.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page