httpcloak

package module
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 6, 2026 License: MIT Imports: 7 Imported by: 1

README

httpcloak

A Go HTTP client library with completely identical to browser TLS/HTTP fingerprinting. This library creates HTTP requests that are indistinguishable from real browsers, bypassing bot detection systems that fingerprint TLS handshakes, HTTP/2 settings, and header patterns.

Why This Library Exists

Modern bot detection systems don't just look at headers or cookies - they analyze the cryptographic fingerprint of your connection itself. Every HTTP client has a unique signature based on:

  1. TLS Fingerprint (JA3/JA4): The cipher suites, extensions, and elliptic curves offered during TLS handshake
  2. HTTP/2 Fingerprint (Akamai): The SETTINGS frame values, WINDOW_UPDATE, PRIORITY frames
  3. Header Order and Values: The exact order and format of HTTP headers

Go's standard net/http library has a recognizable fingerprint that bot detection systems (Cloudflare, Akamai, PerimeterX, DataDome) can identify instantly.

Note: The requests made via this lib definitely passes through most of medium level Cloudflare, Akamai or PerimeterX detection but hardcore ones which check js runtime and other browser fingerprinting is where this will fail.

The Problem with Go's Standard Library

Every TLS connection has a fingerprint. Bot detection services maintain databases of fingerprints for:

  • Every browser version (Chrome 143, Firefox 133, Safari 18, etc.)
  • Known bot libraries (Go net/http, Python requests, curl, etc.)
  • Known automation tools (Selenium, Puppeteer, etc.)

When your Go application connects, the server instantly knows it's not a browser. Here's a side-by-side comparison with real data from tls.peet.ws/api/all:

┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                           FINGERPRINT COMPARISON (Real Data from tls.peet.ws)                        │
├──────────────────────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                                      │
│  METRIC                      │ GO STDLIB              │ HTTPCLOAK              │ REAL CHROME 143     │
│  ────────────────────────────┼────────────────────────┼────────────────────────┼──────────────────── │
│                                                                                                      │
│  TLS FINGERPRINT                                                                                     │
│  ────────────────────────────┼────────────────────────┼────────────────────────┼──────────────────── │
│  Cipher Suites               │ 13                     │ 16                     │ 16                  │
│  TLS Extensions              │ 12                     │ 18                     │ 18                  │
│  GREASE Values               │ None                   │ Yes (random)           │ Yes (random)        │
│  Post-Quantum (X25519MLKEM)  │ No                     │ Yes                    │ Yes                 │
│  ECH (Encrypted ClientHello) │ No                     │ Yes                    │ Yes                 │
│                                                                                                      │
│  CIPHER SUITES (first 5)                                                                             │
│  ────────────────────────────┼────────────────────────┼────────────────────────┼──────────────────── │
│  1st cipher                  │ AES_128_GCM            │ GREASE (random)        │ GREASE (random)     │
│  2nd cipher                  │ AES_256_GCM            │ AES_128_GCM            │ AES_128_GCM         │
│  3rd cipher                  │ CHACHA20_POLY1305      │ AES_256_GCM            │ AES_256_GCM         │
│  4th cipher                  │ ECDHE_ECDSA_AES128     │ CHACHA20_POLY1305      │ CHACHA20_POLY1305   │
│  5th cipher                  │ ECDHE_RSA_AES128       │ ECDHE_ECDSA_AES128     │ ECDHE_ECDSA_AES128  │
│                                                                                                      │
│  SUPPORTED GROUPS                                                                                    │
│  ────────────────────────────┼────────────────────────┼────────────────────────┼──────────────────── │
│  Groups                      │ X25519, P-256,         │ GREASE, X25519MLKEM768,│ GREASE, X25519MLKEM,│
│                              │ P-384, P-521           │ X25519, P-256, P-384   │ X25519, P-256, P-384│
│                                                                                                      │
│  FINGERPRINT HASHES (verified against real Chrome 143)                                               │
│  ────────────────────────────┼────────────────────────┼────────────────────────┼──────────────────── │
│  JA3 Hash*                   │ e69402f870ecf542...    │ (varies per request)   │ (varies per request)│
│  JA4                         │ t13d1312h2_f57a46...   │ t13d1516h2_8daaf6152771_d8a2da3f94cd   MATCH │
│  peetprint_hash              │ (different)            │ 1d4ffe9b0e34acac0bd883fa7f79d7b5       MATCH │
│  Akamai HTTP/2 Hash          │ cbcbfae223bb97a0...    │ 52d84b11737d980aef856699f885ca86       MATCH │
│                                                                                                      │
│  * JA3 includes GREASE values which are randomized per connection (by design)                        │
│                                                                                                      │
│  HTTP/2 SETTINGS FRAME                                                                               │
│  ────────────────────────────┼────────────────────────┼────────────────────────┼──────────────────── │
│  HEADER_TABLE_SIZE           │ 4,096                  │ 65,536                 │ 65,536              │
│  ENABLE_PUSH                 │ 1 (enabled)            │ 0 (disabled)           │ 0 (disabled)        │
│  INITIAL_WINDOW_SIZE         │ 65,535 (64KB)          │ 6,291,456 (6MB)        │ 6,291,456 (6MB)     │
│  MAX_HEADER_LIST_SIZE        │ 10,485,760             │ 262,144                │ 262,144             │
│  WINDOW_UPDATE increment     │ (varies)               │ 15,663,105             │ 15,663,105          │
│                                                                                                      │
│  HTTP/2 HEADERS FRAME                                                                                │
│  ────────────────────────────┼────────────────────────┼────────────────────────┼──────────────────── │
│  Pseudo-header order         │ :method, :path,        │ :method, :authority,   │ :method, :authority,│
│                              │ :scheme, :authority    │ :scheme, :path         │ :scheme, :path      │
│  Header order                │ (Go's alphabetical)    │ sec-ch-ua, sec-ch-ua-  │ sec-ch-ua, sec-ch-  │
│                              │                        │ mobile, sec-ch-ua-     │ ua-mobile, sec-ch-  │
│                              │                        │ platform, upgrade-...  │ ua-platform, ...    │
│  Priority flag               │ Not present            │ Present                │ Present             │
│  Priority weight             │ N/A                    │ 256                    │ 256                 │
│  Priority exclusive          │ N/A                    │ 1                      │ 1                   │
│  Priority depends_on         │ N/A                    │ 0                      │ 0                   │
│                                                                                                      │
│  CLIENT HINTS                                                                                        │
│  ────────────────────────────┼────────────────────────┼────────────────────────┼──────────────────── │
│  sec-ch-ua                   │ (not sent)             │ "Google Chrome";v="143"│ "Google Chrome";v=" │
│                              │                        │ "Chromium";v="143",    │ 143", "Chromium";   │
│                              │                        │ "Not A(Brand";v="24"   │ v="143", "Not A(... │
│                                                                                                      │
│  MATCH STATUS                                                                                        │
│  ────────────────────────────┼────────────────────────┼────────────────────────┼──────────────────── │
│  Matches Chrome 143?         │           NO           │          YES           │     (is Chrome)     │
│  Bot Detection Result        │         BLOCKED        │         PASSED         │        PASSED       │
│                                                                                                      │
└──────────────────────────────────────────────────────────────────────────────────────────────────────┘

Key observations:

  • Akamai HTTP/2 Hash: 52d84b11737d980aef856699f885ca86identical to real Chrome 143
  • JA4 Hash: t13d1516h2_8daaf6152771_d8a2da3f94cdidentical to real Chrome 143
  • peetprint_hash: 1d4ffe9b0e34acac0bd883fa7f79d7b5identical to real Chrome 143
  • GREASE: Both Chrome and httpcloak randomize GREASE values per connection (this is correct behavior)
  • JA3 varies: JA3 includes GREASE values, so it changes per connection — this is expected and correct
  • Priority frame: Chrome 143 sends Priority data (weight=256, exclusive=1), and so does httpcloak
  • Header order: Both send sec-ch-ua headers first, matching Chrome's exact ordering
Why Each Metric Matters
Metric Why It Matters
Cipher Suites Browsers offer more ciphers in a specific order. Go offers fewer in a different order. This alone identifies Go.
TLS Extensions Chrome sends 18 extensions including GREASE (random values). Go sends 12 with no GREASE. Dead giveaway.
Post-Quantum Chrome 131+ uses X25519MLKEM768 for quantum-resistant key exchange. Go doesn't support this yet.
GREASE Generate Random Extensions And Sustain Extensibility - Chrome randomizes these values per connection. Using the same GREASE value every time is itself a fingerprint!
JA3/JA4 Hash JA4 is the modern standard (JA3 is deprecated due to GREASE). Bot detection services maintain databases of known JA4 hashes.
HTTP/2 SETTINGS The first HTTP/2 frame contains settings. Chrome's values differ significantly from Go's defaults.
INITIAL_WINDOW_SIZE Chrome uses 6MB, Go uses 64KB. This 100x difference is instantly detectable.
Priority Frame Chrome 143 sends Priority data (weight=256, exclusive=1) on HEADERS frames. Go doesn't send this.
Header Order Chrome sends headers in a specific order (sec-ch-ua first). Go uses alphabetical order. The order itself is a fingerprint.
sec-ch-ua Brand Chrome 143 uses "Not A(Brand";v="24". Older/wrong brand strings identify automation.
What Gets You Blocked
┌─────────────────────────────────────────────────────────────────┐
│                    BOT DETECTION LAYERS                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  Layer 1: TLS Fingerprint                                       │
│  ├─ JA3/JA4 hash lookup in known-bot database                   │
│  ├─ Cipher suite count and order analysis                       │
│  ├─ Extension presence check (GREASE, etc.)                     │
│  └─ Post-quantum support detection                              │
│       ↓ FAIL = Instant block (403/503)                          │
│                                                                 │
│  Layer 2: HTTP/2 Fingerprint                                    │
│  ├─ SETTINGS frame analysis                                     │
│  ├─ WINDOW_UPDATE patterns                                      │
│  └─ PRIORITY frame structure                                    │
│       ↓ FAIL = Captcha or block                                 │
│                                                                 │
│  Layer 3: Header Analysis                                       │
│  ├─ Header order (browsers have specific order)                 │
│  ├─ Sec-Fetch-* header coherence                                │
│  └─ Client Hints presence                                       │
│       ↓ FAIL = Suspicious flag                                  │
│                                                                 │
│  Layer 4: JavaScript Challenge (not covered by httpcloak)       │
│  ├─ Canvas fingerprint                                          │
│  ├─ WebGL fingerprint                                           │
│  └─ Browser API probing                                         │
│       ↓ FAIL = Block                                            │
│                                                                 │
│  httpcloak passes Layers 1-3                                    │
│  Layer 4 requires actual browser or specialized tools           │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
How httpcloak Solves This

httpcloak uses uTLS to perfectly mimic browser TLS handshakes, combined with:

  • Correct HTTP/2 SETTINGS, WINDOW_UPDATE, and PRIORITY frames
  • Browser-accurate header ordering (:method, :authority, :scheme, :path pseudo-headers)
  • Proper Sec-Fetch-* headers for navigation vs CORS requests
  • Client Hints (Sec-Ch-Ua-*) matching the spoofed browser
  • Organic jitter in quality values to match real browser behavior

The result: requests are cryptographically indistinguishable from a real Chrome browser.

Installation

go get github.com/sardanioss/httpcloak

Quick Start

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/sardanioss/httpcloak/client"
)

func main() {
    // Create client with Chrome 143 fingerprint
    c := client.NewClient("chrome-143")
    defer c.Close()

    // Make a request - looks exactly like Chrome to the server
    resp, err := c.Get(context.Background(), "https://example.com", nil)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Status: %d\n", resp.StatusCode)
    fmt.Printf("Protocol: %s\n", resp.Protocol) // "h2" or "h3"
    fmt.Println(resp.Text())
}

How TLS Fingerprinting Works

When your client connects to a server over HTTPS, the TLS handshake exposes identifying information:

┌──────────────────────────────────────────────────────────────────┐
│                      TLS CLIENT HELLO                            │
├──────────────────────────────────────────────────────────────────┤
│ TLS Version: 1.3                                                 │
│                                                                  │
│ Cipher Suites (ordered list):                                    │
│   TLS_AES_128_GCM_SHA256                                         │
│   TLS_AES_256_GCM_SHA384                                         │
│   TLS_CHACHA20_POLY1305_SHA256                                   │
│   TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256                        │
│   ... (16 total for Chrome, 13 for Go)                           │
│                                                                  │
│ Extensions (ordered list):                                       │
│   server_name (SNI)                                              │
│   extended_master_secret                                         │
│   signature_algorithms                                           │
│   supported_versions                                             │
│   psk_key_exchange_modes                                         │
│   key_share (with X25519MLKEM768 for Chrome 131+)                │
│   application_layer_protocol_negotiation                         │
│   ... (18 total for Chrome, 12 for Go)                           │
│                                                                  │
│ Supported Groups (elliptic curves):                              │
│   X25519MLKEM768 (post-quantum, Chrome 131+)                     │
│   X25519                                                         │
│   P-256                                                          │
│   P-384                                                          │
├──────────────────────────────────────────────────────────────────┤
│                             ↓                                    │
│                   JA3/JA4 Fingerprint                            │
│                             ↓                                    │
│            Server knows you're Go, not Chrome                    │
└──────────────────────────────────────────────────────────────────┘

JA3 hashes these fields into a fingerprint. JA4 is the newer standard with more detail. Bot detection services maintain databases of fingerprints for every browser version and known bot libraries.

How HTTP/2 Fingerprinting Works

After TLS, the HTTP/2 connection also has a fingerprint based on the SETTINGS frame:

┌──────────────────────────────────────────────────────────────────┐
│                    HTTP/2 SETTINGS FRAME                         │
├──────────────────────────────────────────────────────────────────┤
│ Go stdlib                      │ Chrome (httpcloak)              │
├────────────────────────────────┼─────────────────────────────────┤
│ HEADER_TABLE_SIZE: 4096        │ HEADER_TABLE_SIZE: 65536        │
│ ENABLE_PUSH: 1                 │ ENABLE_PUSH: 0                  │
│ MAX_CONCURRENT_STREAMS: 250    │ MAX_CONCURRENT_STREAMS: 1000    │
│ INITIAL_WINDOW_SIZE: 65535     │ INITIAL_WINDOW_SIZE: 6291456    │
│ MAX_FRAME_SIZE: 16384          │ MAX_FRAME_SIZE: 16384           │
│ MAX_HEADER_LIST_SIZE: 10485760 │ MAX_HEADER_LIST_SIZE: 262144    │
└──────────────────────────────────────────────────────────────────┘

These settings are hashed into the Akamai fingerprint. httpcloak sends the exact values Chrome uses.

Features

Browser Fingerprints
  • TLS Fingerprinting: JA3/JA4 fingerprints match real Chrome/Firefox
  • HTTP/2 Fingerprinting: SETTINGS, WINDOW_UPDATE, PRIORITY frames match browsers
  • HTTP/3 Support: QUIC with proper fingerprinting
  • HTTP/1.1 Support: For legacy servers with browser-like header ordering
  • Client Hints: Sec-Ch-Ua-* headers matching the spoofed browser
  • Header Coherence: Sec-Fetch-* headers are always consistent
Protocol Support
  • Auto Protocol Selection: Tries HTTP/3 → HTTP/2 → HTTP/1.1 with smart fallback
  • Protocol Learning: Remembers which protocol each host supports
  • Force Protocol: Can force specific protocol (H1, H2, or H3) per request
  • Plain HTTP: Automatically uses HTTP/1.1 for non-TLS connections
HTTP Features
  • Connection Pooling: Efficient connection reuse (H2 multiplexing, H1 keep-alive)
  • Session Management: Cookie jar for persistent sessions (like requests.Session())
  • Automatic Decompression: gzip, brotli, zstd
  • Redirect Following: Configurable, with history tracking (resp.RedirectHistory)
  • Retry with Backoff: Exponential backoff with jitter
  • Proxy Support: HTTP, HTTPS, SOCKS5 proxies
  • Authentication: Basic, Bearer, Digest auth
  • Better Error Handling: Categorized errors (DNS, TLS, timeout, connection) with retry hints
  • Request Hooks: Pre-request and post-response callbacks
  • Prepared Requests: Inspect and modify requests before sending
  • Certificate Pinning: Pin certificates by SPKI hash for security
Request Modes
  • Navigate Mode: Simulates user-initiated navigation (Sec-Fetch-Mode: navigate)
  • CORS Mode: Simulates JavaScript fetch() call (Sec-Fetch-Mode: cors)
  • Organic Jitter: Random header variations to match real browser inconsistencies

Available Presets

Preset Browser TLS HTTP/2 HTTP/3
chrome-143 Chrome 143 X25519MLKEM768
chrome-143-windows Chrome 143 (Windows) X25519MLKEM768
chrome-141 Chrome 141 X25519MLKEM768
chrome-133 Chrome 133 X25519MLKEM768
chrome-131 Chrome 131 X25519MLKEM768
firefox-133 Firefox 133 X25519
safari-18 Safari 18 X25519

Presets auto-adapt to your OS (Windows/macOS/Linux) for User-Agent and Sec-Ch-Ua-Platform.

Usage Examples

Simple GET Request
c := client.NewClient("chrome-143")
defer c.Close()

resp, err := c.Get(ctx, "https://api.example.com/data", nil)
if err != nil {
    log.Fatal(err)
}

fmt.Println(resp.Text())
Session with Cookies
// NewSession automatically persists cookies between requests
session := client.NewSession("chrome-143")
defer session.Close()

// Login - cookies are saved
session.Post(ctx, "https://example.com/login",
    []byte(`{"user":"test","pass":"secret"}`),
    map[string]string{"Content-Type": "application/json"})

// Subsequent requests include cookies automatically
resp, _ := session.Get(ctx, "https://example.com/dashboard", nil)
API Request (CORS Mode)
c := client.NewClient("chrome-143")
defer c.Close()

resp, err := c.Do(ctx, &client.Request{
    Method:    "POST",
    URL:       "https://api.example.com/graphql",
    Body:      []byte(`{"query": "{ user { name } }"}`),
    FetchMode: client.FetchModeCORS,  // Simulates fetch() call
    Referer:   "https://app.example.com/",
    Headers: map[string]string{
        "Content-Type": "application/json",
    },
})
With Proxy
c := client.NewClient("chrome-143",
    client.WithProxy("http://user:pass@proxy.example.com:8080"),
    client.WithTimeout(60*time.Second),
)
defer c.Close()
With Retry
c := client.NewClient("chrome-143",
    client.WithRetry(3),  // Retry up to 3 times on 429, 500, 502, 503, 504
)
defer c.Close()
Force Protocol
// Force HTTP/1.1 (for legacy servers or specific requirements)
resp, err := c.Do(ctx, &client.Request{
    Method:        "GET",
    URL:           "https://example.com",
    ForceProtocol: client.ProtocolHTTP1,
})

// Force HTTP/2 (skip HTTP/3 attempt)
resp, err := c.Do(ctx, &client.Request{
    Method:        "GET",
    URL:           "https://example.com",
    ForceProtocol: client.ProtocolHTTP2,
})

// Force HTTP/3
resp, err := c.Do(ctx, &client.Request{
    Method:        "GET",
    URL:           "https://example.com",
    ForceProtocol: client.ProtocolHTTP3,
})

// Auto (default) - tries H3 → H2 → H1 with smart fallback
resp, err := c.Do(ctx, &client.Request{
    Method:        "GET",
    URL:           "https://example.com",
    ForceProtocol: client.ProtocolAuto,
})
Request Hooks
c := client.NewClient("chrome-143")
defer c.Close()

// Add pre-request hook (logging, modification)
c.OnPreRequest(func(req *http.Request) error {
    log.Printf("Requesting: %s %s", req.Method, req.URL)
    req.Header.Set("X-Custom-Header", "value")
    return nil
})

// Add post-response hook (logging, metrics)
c.OnPostResponse(func(resp *client.Response) error {
    log.Printf("Response: %d from %s", resp.StatusCode, resp.FinalURL)
    return nil
})

resp, _ := c.Get(ctx, "https://example.com", nil)
Prepared Requests
c := client.NewClient("chrome-143")
defer c.Close()

// Prepare a request without sending
prepared, err := c.Prepare(ctx, &client.Request{
    Method: "POST",
    URL:    "https://api.example.com/data",
    Body:   []byte(`{"key": "value"}`),
})

// Inspect and modify before sending
prepared.SetHeader("X-Request-ID", "abc123")
prepared.SetHeader("Authorization", "Bearer token")

// Send when ready
resp, err := prepared.Send(ctx)
Certificate Pinning
c := client.NewClient("chrome-143")
defer c.Close()

// Pin by SPKI SHA256 hash (base64 encoded)
c.PinCertificate("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
    client.ForHost("api.example.com"),
    client.IncludeSubdomains())

// Or load from certificate file
err := c.PinCertificateFromFile("/path/to/cert.pem",
    client.ForHost("api.example.com"))

// Requests will fail if certificate doesn't match pin
resp, err := c.Get(ctx, "https://api.example.com/data", nil)
if err != nil {
    // Check if it's a pinning error
    var pinErr *client.CertPinError
    if errors.As(err, &pinErr) {
        log.Printf("Certificate pinning failed: %v", pinErr)
    }
}
Redirect History
c := client.NewClient("chrome-143")
defer c.Close()

resp, _ := c.Get(ctx, "https://example.com/redirect-chain", nil)

// Access redirect history
for i, redirect := range resp.RedirectHistory {
    fmt.Printf("Redirect %d: %d -> %s\n", i+1, redirect.StatusCode, redirect.URL)
}
fmt.Printf("Final URL: %s\n", resp.FinalURL)

Examples

The examples/ directory contains runnable examples:

# Basic usage - GET, POST, headers, timeout, redirects, retry, SSL, protocols
go run examples/basic/main.go

# Session management - cookies, login flow, cookie inspection
go run examples/session/main.go

# Cloudflare trace - multiple requests, protocol comparison
go run examples/cloudflare/main.go

Architecture

httpcloak/
├── httpcloak.go       # High-level public API
├── client/
│   ├── client.go      # HTTP client with fingerprint spoofing
│   ├── options.go     # Configuration options
│   ├── cookie.go      # Cookie handling
│   ├── cookiejar.go   # Cookie jar implementation
│   ├── auth.go        # Authentication (Basic, Bearer, Digest)
│   ├── multipart.go   # Multipart form data
│   ├── stream.go      # SSE/streaming support
│   ├── url.go         # URL building utilities
│   ├── helpers.go     # Utility functions
│   ├── hooks.go       # Request hooks (pre/post callbacks)
│   ├── prepared.go    # Prepared requests pattern
│   ├── certpin.go     # Certificate pinning
│   └── http3_client.go # HTTP/3 client implementation
├── fingerprint/
│   └── presets.go     # Browser fingerprint definitions (TLS + HTTP/2)
├── transport/
│   ├── transport.go       # Unified transport (H1/H2/H3 with auto-fallback)
│   ├── http1_transport.go # HTTP/1.1 with uTLS and keep-alive pooling
│   ├── http2_transport.go # HTTP/2 with custom TLS
│   ├── http3_transport.go # HTTP/3 (QUIC)
│   ├── http2_custom.go    # Custom HTTP/2 framing
│   └── errors.go          # Categorized errors (DNS, TLS, timeout, etc.)
├── pool/
│   ├── pool.go        # Connection pool for HTTP/2
│   └── quic_pool.go   # Connection pool for HTTP/3
├── dns/
│   └── cache.go       # DNS caching
├── session/
│   ├── session.go     # Session management
│   └── manager.go     # Session manager
├── protocol/
│   └── types.go       # IPC protocol types for multi-language support
└── cmd/
    └── httpcloak-daemon/
        ├── main.go    # IPC daemon for Python/Node.js/Ruby SDKs
        └── ipc_test.go # Comprehensive IPC tests

Multi-Language Support (IPC Daemon)

httpcloak includes an IPC daemon for use from any programming language via JSON over stdin/stdout.

# Build the daemon
go build -o httpcloak-daemon ./cmd/httpcloak-daemon/

# Simple request
echo '{"id":"1","type":"request","method":"GET","url":"https://example.com"}' | ./httpcloak-daemon
Message Types
Type Description
ping Health check
preset.list List available browser presets
session.create Create session with cookies
session.close / session.list Manage sessions
request Make HTTP request
cookie.get / cookie.set / cookie.clear / cookie.all Cookie management
Example: Python
import subprocess, json

proc = subprocess.Popen(['./httpcloak-daemon'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)

def send(msg):
    proc.stdin.write(json.dumps(msg) + '\n')
    proc.stdin.flush()
    return json.loads(proc.stdout.readline())

# Create session with Chrome 143 fingerprint
session = send({"id": "1", "type": "session.create", "options": {"preset": "chrome-143"}})

# Make request
resp = send({"id": "2", "type": "request", "session": session["session"], "method": "GET", "url": "https://example.com"})
print(f"Status: {resp['status']}, Protocol: {resp['protocol']}")
Request Options
{
    "id": "1", "type": "request", "session": "session-123",
    "method": "POST", "url": "https://api.example.com/data",
    "headers": {"Content-Type": "application/json"},
    "body": "{\"key\": \"value\"}",
    "options": {
        "timeout": 30000, "followRedirects": true, "forceProtocol": "h2",
        "fetchMode": "cors", "referer": "https://example.com/",
        "proxy": "http://user:pass@proxy:8080",
        "auth": {"type": "bearer", "token": "your-token"}
    }
}
Future SDKs
Language Status
Go github.com/sardanioss/httpcloak
Python 🔜 Planned
Node.js 🔜 Planned

Testing

Run the TLS fingerprint comparison test to verify httpcloak produces different fingerprints than Go's stdlib:

go test -v ./client -run TestTLSFingerprint_Comparison

This test:

  1. Fetches https://tls.peet.ws/api/all with Go's net/http
  2. Fetches the same URL with httpcloak
  3. Compares JA3, JA4, and Akamai fingerprints
  4. Asserts they are different (proving the fingerprint spoofing works)

Comparison with Other Libraries

Feature net/http resty httpcloak
TLS Fingerprint Spoofing
HTTP/2 Fingerprint Spoofing
HTTP/3 Support
Browser-like Headers
Connection Pooling
Cookie Jar
Bypasses Bot Detection

Security Considerations

This library is intended for:

  • Web scraping where you have permission
  • Automated testing of your own services
  • Research and security analysis
  • Bypassing overly aggressive bot detection on legitimate use

Do not use for:

  • Unauthorized access to systems
  • Circumventing security for malicious purposes
  • Violating terms of service

License

MIT

Dependencies

This library uses custom forks to enable browser-accurate fingerprinting:

Library Fork Why
uTLS sardanioss/utls Chrome 143 QUIC preset, platform-specific TLS fingerprints
quic-go sardanioss/quic-go uTLS integration, Chrome HTTP/3 SETTINGS, custom transport params
net sardanioss/net HTTP/2 fingerprinting (SETTINGS, WINDOW_UPDATE, PRIORITY frames)

Credits

  • uTLS - TLS fingerprint spoofing (upstream)
  • quic-go - HTTP/3 implementation (upstream)
  • tls.peet.ws - TLS fingerprint analysis

AI Assistance Note

I used claude code mainly to write code and a lot of it is written with its help. Just wanted to add this info, Thank you!

Documentation

Overview

Package httpcloak provides an HTTP client with perfect browser TLS/HTTP fingerprinting.

httpcloak allows you to make HTTP requests that are indistinguishable from real browsers, bypassing TLS fingerprinting, HTTP/2 fingerprinting, and header-based bot detection.

Basic usage:

client := httpcloak.New("chrome-131")
defer client.Close()

resp, err := client.Get(ctx, "https://example.com")
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(resp.Body))

With options:

client := httpcloak.New("chrome-131",
    httpcloak.WithTimeout(30*time.Second),
    httpcloak.WithProxy("http://user:pass@proxy:8080"),
)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Presets

func Presets() []string

Presets returns available fingerprint presets

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is an HTTP client with browser fingerprint spoofing

func New

func New(preset string, opts ...Option) *Client

New creates a new HTTP client with the specified browser fingerprint.

Available presets:

  • "chrome-131" (recommended)
  • "chrome-131-windows"
  • "chrome-131-macos"
  • "chrome-133"
  • "chrome-133-windows"

Example:

client := httpcloak.New("chrome-131")
defer client.Close()

func (*Client) Close

func (c *Client) Close()

Close releases all resources held by the client

func (*Client) Do

func (c *Client) Do(ctx context.Context, req *Request) (*Response, error)

Do executes an HTTP request

func (*Client) Get

func (c *Client) Get(ctx context.Context, url string) (*Response, error)

Get performs a GET request

func (*Client) GetWithHeaders

func (c *Client) GetWithHeaders(ctx context.Context, url string, headers map[string]string) (*Response, error)

GetWithHeaders performs a GET request with custom headers

func (*Client) Post

func (c *Client) Post(ctx context.Context, url string, body []byte, contentType string) (*Response, error)

Post performs a POST request

func (*Client) PostForm

func (c *Client) PostForm(ctx context.Context, url string, body []byte) (*Response, error)

PostForm performs a POST request with form data

func (*Client) PostJSON

func (c *Client) PostJSON(ctx context.Context, url string, body []byte) (*Response, error)

PostJSON performs a POST request with JSON body

type Option

type Option func(*clientConfig)

Option configures the Client

func WithProxy

func WithProxy(proxyURL string) Option

WithProxy sets an HTTP/HTTPS/SOCKS5 proxy

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the request timeout

type Request

type Request struct {
	Method  string
	URL     string
	Headers map[string]string
	Body    []byte
	Timeout time.Duration
}

Request represents an HTTP request

type Response

type Response struct {
	StatusCode int
	Headers    map[string]string
	Body       []byte
	FinalURL   string
	Protocol   string
}

Response represents an HTTP response

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session represents a persistent HTTP session with cookie management

func NewSession

func NewSession(preset string, opts ...SessionOption) *Session

NewSession creates a new persistent session with cookie management

func (*Session) Close

func (s *Session) Close()

Close closes the session and releases resources

func (*Session) Do

func (s *Session) Do(ctx context.Context, req *Request) (*Response, error)

Do executes a request within the session, maintaining cookies

func (*Session) Get

func (s *Session) Get(ctx context.Context, url string) (*Response, error)

Get performs a GET request within the session

func (*Session) GetCookies

func (s *Session) GetCookies() map[string]string

GetCookies returns all cookies stored in the session

func (*Session) SetCookie

func (s *Session) SetCookie(name, value string)

SetCookie sets a cookie in the session

type SessionOption

type SessionOption func(*sessionConfig)

SessionOption configures a session

func WithSessionProxy

func WithSessionProxy(proxyURL string) SessionOption

WithSessionProxy sets a proxy for the session

func WithSessionTimeout

func WithSessionTimeout(d time.Duration) SessionOption

WithSessionTimeout sets the timeout for session requests

Directories

Path Synopsis
Package client provides an HTTP client with browser TLS/HTTP fingerprint spoofing.
Package client provides an HTTP client with browser TLS/HTTP fingerprint spoofing.
cmd
check_hello command
test_cloudflare command
examples
basic command
Example: Basic HTTP requests with httpcloak
Example: Basic HTTP requests with httpcloak
cloudflare command
Example: Multiple requests to Cloudflare trace endpoint
Example: Multiple requests to Cloudflare trace endpoint
session command
Example: Session management with cookies
Example: Session management with cookies
Package protocol defines the IPC message types for communication between the httpcloak daemon and language SDKs (Python, Node.js, etc.)
Package protocol defines the IPC message types for communication between the httpcloak daemon and language SDKs (Python, Node.js, etc.)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL