Spectre HTTP Client
A highly efficient HTTP/HTTPS client in Rust with Python bindings that impersonates real browsers (Chrome, Firefox, Safari, Edge) at the network stack level while minimizing bandwidth usage through intelligent caching and compression.
Features
- Browser Impersonation: Network-level impersonation of Chrome, Firefox, Safari, and Edge
- TLS fingerprinting (JA4/JA4H compatible)
- HTTP/2 settings per browser
- TCP configuration per OS
- User-Agent and header matching
- Client Hints (Sec-CH-UA-*)
- Sec-Fetch-* headers
- Post-Quantum TLS: Optional X25519MLKem768 hybrid key exchange (Chrome 131+)
- Bandwidth Optimization:
- ETag/Last-Modified conditional requests
- Automatic decompression (Brotli, Gzip, Deflate, Zstd)
- Wire size tracking
- Smart Caching: In-memory cache with Cache-Control support
- Cookie Management: Automatic cookie storage and sending
- Connection Pooling: Efficient HTTP/2 and HTTP/1.1 connection reuse with configurable limits
- Proxy Support:
- HTTP CONNECT and SOCKS5 proxy support
- Runtime proxy switching (change proxy without recreating client)
- Split proxy configuration (different proxy for HTTP/1-2 vs HTTP/3)
- Smart proxy rotation with health checking
- Advanced Routing:
- Domain fronting (SNI override for CDN routing)
- Request timing metrics (DNS, TCP, TLS, TTFB)
- HTTP/3 support with automatic fallback
- Encrypted Client Hello (ECH) support
- Middleware System: Composable request/response processing
- Rate limiting
- Request logging
- Circuit breaker
- Custom middleware support
- Authentication: Built-in auth helpers
- Bearer token with auto-refresh
- Basic auth caching
- Digest auth (RFC 2617)
- NTLM support
- Observability:
- Request/response metrics collection
- Performance percentiles (p50, p90, p95, p99)
- Per-request timing breakdown
- Custom Headers: Set custom headers per client that override defaults
- Python Bindings: Full async Python API via PyO3 (Python 3.8+)
- Certificate Pinning: SPKI hash-based certificate verification
- Session Persistence: Save/load sessions with cookies and TLS tickets
Documentation
- Rust Documentation - API documentation for Rust
- Python Examples - Example scripts demonstrating Python usage
- Rust Examples - Example programs for Rust
Table of Contents
- Installation
- Quick Start
- Available Browser Profiles
- Python API Reference
- Rust API Reference
- Advanced Features
Installation
From PyPI
From Source
# Build the Rust library
# Build the Python wheel
# Install the wheel
Development Install
Requirements
- Rust: 1.93.0 or later
- Python: 3.13 or later (for Python bindings)
Quick Start
Usage
Rust
Add spectreq to your Cargo.toml.
use ;
async
See examples/*.rs for more examples:
Python
Install via pip:
=
=
= await
See examples/python/*.py for more examples:
With Proxy and Custom Headers
=
# Create client with proxy and custom headers
=
## Available Browser Profiles
### Chrome Profiles
| | | | - |
|--------|---------|-----|-------------------|
| `` | 120.0.6099.109 | 11 | /5.0 ... |
| `` | 120.0.6099.109 | | /5.0 ... |
| `` | 120.0.6099.109 | | /5.0 ... |
| `` | 120.0.6099.43 | 13 | /5.0 ... |
| `` | 131.0.0.0 | 11 | /5.0 ... /131... |
| `` | 133.0.0.0 | 11 | /5.0 ... /133... |
| `` | 141.0.0.0 | 11 | /5.0 ... /141... |
| `` | 143.0.0.0 | 11 | /5.0 ... /143... |
| `` | 143.0.0.0 | | /5.0 ... /143... |
| `` | 143.0.0.0 | | /5.0 ... /143... |
| `` | 143.0.6099.43 | 13 | /5.0 ... /143... |
****: 131+ /2 .
### Firefox Profiles
| | | | - |
|--------|---------|-----|-------------------|
| `` | 121.0 | 11 | /5.0 ... |
### Safari Profiles
| | | | - |
|--------|---------|-----|-------------------|
| `` | 17.0 | | /5.0 ... |
### Edge Profiles
| | | | - |
|--------|---------|-----|-------------------|
| `` | 120.0.2210.61 | 11 | /5.0 ... /120.0.2210.61 |
## Python API Reference
### Profile Class
`` -
#### Static Methods
```
# Chrome 120 Series
# Chrome 131+ Series (with larger HTTP/2 window size)
# Chrome 143 Series (latest)
# Firefox
# Safari
# Edge
# Random profile selection (anti-detection)
# Random from all browsers
# Random Chrome profile
# Load from file
# Load from string
Anti-Detection Features
# Get a random profile each request
=
# Or randomize session-specific values
=
# Export profile for later use
=
=
Properties
=
# Get browser name
# "Chrome"
# Get operating system
# "Windows"
# Get version string
# "143.0.0.0"
# Get user agent string
# Full UA string
# Get profile as dict for debugging
=
# {'browser': 'Chrome', 'os': 'Windows', 'version': '143.0.0.0', ...}
Client Class
Constructor
# Create client with profile
=
# With proxy
=
# With custom headers (overrides defaults)
=
# With both proxy and headers
=
Properties
# Get the proxy configuration
= # None or "http://proxy.example.com:8080"
# Get custom headers
= # Dict of custom headers
HTTP Methods
All HTTP methods are async and return a Response object.
# GET request
= await
# POST request with bytes
= await
# POST request with string
= await
# PUT request
= await
# DELETE request
= await
# PATCH request
= await
# HEAD request
= await
Response Class
Properties
= await
# HTTP status code
= # 200
# Wire size (compressed size from network)
= # 366
# Whether response was from cache (304 Not Modified)
= # False or True
Methods
# Get response body as text
= # "<!doctype html>..."
# Get response body as bytes
= # b"<!doctype html>..."
# Parse response as JSON
= # {"key": "value"}
# Get all headers as dict
=
# {"content-type": "text/html", "content-length": "1256"}
# Get specific header value
= # "text/html"
= # '"33a64af5573fc"'
# Check if request was successful (2xx status)
HTTP Methods Reference
Default Headers
All requests include these headers automatically:
| Header | Default Value | Notes |
|---|---|---|
User-Agent |
From profile | Browser-specific |
Accept |
*/* |
|
Accept-Encoding |
From profile | gzip, deflate, br, zstd |
Connection |
keep-alive |
|
Cookie |
Auto-added | If cookies exist |
Conditional Request Headers
For GET and HEAD requests, the client automatically adds:
| Header | When Added | Description |
|---|---|---|
If-None-Match |
Cached ETag exists | ETag-based validation |
If-Modified-Since |
Cached Last-Modified exists | Time-based validation |
Supported HTTP Methods
| Method | Body Support | Cache Support |
|---|---|---|
| GET | No | Yes (ETag, Last-Modified) |
| POST | Yes | No |
| PUT | Yes | No |
| DELETE | No | No |
| PATCH | Yes | No |
| HEAD | No | Yes (ETag, Last-Modified) |
Caching
The client includes an in-memory cache that respects:
- ETag: Sends
If-None-Matchheader - Last-Modified: Sends
If-Modified-Sinceheader - Cache-Control: Respects
max-agedirective
Default Cache Behavior
| Setting | Default |
|---|---|
| Cache enabled | Yes |
| Default max-age (if not specified) | 5 minutes (300 seconds) |
| Cache key format | METHOD:URL |
Cache Example
# First request - fetches from server
= await
# e.g., 366 bytes
# Second request - may return 304 with cached body
= await
# True if 304
# 0 if 304
Compression Support
The client automatically decompresses responses based on the Content-Encoding header.
Supported Compression Types
| Encoding | Support | Compression Ratio |
|---|---|---|
Brotli (br) |
Yes | ~15-25% |
Gzip (gzip) |
Yes | ~20-30% |
Deflate (deflate) |
Yes | ~20-30% |
Zstd (zstd) |
Yes | ~15-25% |
Identity (identity) |
Yes | 100% (no compression) |
Compression Example
# Accept-Encoding header is set automatically
= await
# Wire size is the compressed size
# Body is automatically decompressed
Cookie Management
The client automatically stores and sends cookies.
Cookie Methods (Rust only)
// Get cookie value for a URL
let cookie_value = client.cookie_jar.get_cookie_value;
// Set cookies from Set-Cookie headers
client.cookie_jar.set_cookies;
// Clear all cookies
client.cookie_jar.clear;
// Get number of cookies
let count = client.cookie_jar.len;
// Check if empty
let empty = client.cookie_jar.is_empty;
// Remove cookies for a domain
client.cookie_jar.remove_for_domain;
Proxy Support
Spectre supports HTTP/HTTPS proxies with automatic CONNECT method handling for HTTPS URLs.
Proxy Configuration
# HTTP proxy
=
# HTTPS proxy with authentication
=
# From environment variable
=
=
How It Works
- HTTP URLs: Direct connection to proxy, hyper handles the request
- HTTPS URLs: Uses HTTP CONNECT method to establish a tunnel through the proxy
- Client connects to proxy
- Sends
CONNECT host:port HTTP/1.1request - Proxy returns
200 Connection established - TLS handshake is performed through the tunnel
- Encrypted data flows through the proxy
Proxy URL Format
http://[user:password@]host[:port]
https://[user:password@]host[:port]
Examples:
http://proxy.example.com:8080http://user:pass@proxy.example.com:8080http://proxy.example.com(defaults to port 8080)
Custom Headers
Custom headers can be set per client and will override default headers.
Setting Custom Headers
# Set custom headers that override defaults
=
Default Headers
These headers are set by default (can be overridden):
| Header | Default Value |
|---|---|
User-Agent |
From profile |
Accept |
*/* |
Accept-Encoding |
From profile (e.g., gzip, deflate, br, zstd) |
Connection |
keep-alive |
Header Priority
Custom headers have higher priority and will override defaults:
# This will override the default Accept-Encoding
=
TLS Fingerprinting
Each profile has unique TLS settings to match real browsers:
| Browser | Cipher Suites | Extensions | GREASE | ALPN |
|---|---|---|---|---|
| Chrome 120 | 9 ciphers | 7 extensions | Yes | h2, http/1.1 |
| Firefox 121 | 7 ciphers | 7 extensions | No | h2, http/1.1 |
| Safari 17 | 5 ciphers | 7 extensions | No | h2, http/1.1 |
| Edge 120 | 3 ciphers | 7 extensions | Yes | h2, http/1.1 |
TLS Configuration (Profile Builder)
use Profile;
let custom_profile = builder
.browser
.os
.version
.user_agent
.http2_initial_window_size
.http2_max_concurrent_streams
.http2_header_table_size
.tls_cipher_suites
.tls_grease
.tcp_ttl
.build;
HTTP/2 Settings
| Setting | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| Initial Window Size | 65536 | 65535 | 65536 | 65536 |
| Max Concurrent Streams | 256 | 100 | 100 | 256 |
| Header Table Size | 65536 | 4096 | 4096 | 65536 |
Error Handling
Python
= await
Rust
use SpectreError;
match client.get.await
Error Types
| Error | Description |
|---|---|
Tls |
TLS handshake or certificate errors |
Http |
HTTP protocol errors |
Connection |
Network connection errors |
InvalidProfile |
Profile configuration errors |
Compression |
Decompression errors |
InvalidUrl |
URL parsing errors |
Timeout |
Request timeout |
Io |
File/IO errors |
Hyper |
Hyper client errors |
Advanced Examples
Python Examples
The following example scripts are available in the examples/python/ directory:
| Example | Description |
|---|---|
basic_request.py |
Simple GET request demonstration |
cookies_demo.py |
CookieJar and session management |
timing_demo.py |
Response timing and metrics |
post_request.py |
POST request with JSON data |
profiles.py |
Display all available browser profiles |
Run examples with:
Rust Examples
The following example programs are available in examples/:
| Example | Description |
|---|---|
basic.rs |
Simple GET request |
cookies.rs |
Cookie management |
timing.rs |
Request timing metrics |
Run examples with:
Multiple Requests with Different Profiles
=
=
= await
POST with JSON
=
=
=
= await
Download with Progress
=
=
= await
Custom Profile in Rust
use ;
let custom = builder
.browser
.os
.version
.user_agent
.build;
let client = new.await?;
Performance Tips
- Reuse Clients: Create one client and reuse it for multiple requests
- Enable Caching: Default caching reduces bandwidth for repeated requests
- Use HTTP/2: All profiles support HTTP/2 for multiplexing
- Compression: Automatic compression reduces bandwidth by ~70-85%
- Connection Pooling: Reuses connections automatically for better performance
- Proxy Rotation: Smart rotation with health checking improves reliability
Advanced Features (Rust API)
Spectre provides advanced features beyond basic HTTP requests. These are available in the Rust API:
Runtime Proxy Switching
Change proxy configuration without recreating the client:
use Client;
use Profile;
async
Domain Fronting
Override SNI and connect target for CDN routing:
use Profile;
// Create profile with domain fronting
let profile = builder
.browser
.os
.version
// Connect to CDN but SNI to origin
.connect_to
.sni_override
.build;
Request Timing Metrics
Get detailed timing information for each request:
use Client;
let resp = client.get.await?;
// Access timing metrics
println!;
println!;
println!;
println!;
println!;
HTTP/3 with Automatic Fallback
HTTP/3 support with automatic fallback to HTTP/2 and HTTP/1.1:
use ;
let profile = chrome_143_windows;
// Client with HTTP/3 enabled (requires "http3" feature)
let mut client = new.await?;
client.set_http3_enabled;
client.set_preferred_http_version;
// Will try HTTP/3, fall back to HTTP/2, then HTTP/1.1
let resp = client.get.await?;
println!;
Encrypted Client Hello (ECH)
Enable ECH for better privacy:
use Profile;
// Enable ECH with auto-discovery
let profile = chrome_143_windows
.with_ech_enabled
.with_ech_config;
let client = new.await?;
let resp = client.get.await?;
Connection Pooling
Configure connection pool behavior:
use ;
let pool_config = new
.max_connections_per_host
.max_idle_connections
.idle_timeout
.max_lifetime
.enabled;
let profile = chrome_143_windows;
let mut client = new.await?;
client.set_pool_config;
// Check pool statistics
let stats = client.pool_stats.await?;
println!;
println!;
Smart Proxy Rotation
Automatic proxy rotation with health checking:
use ;
use Duration;
// Configure rotation behavior
let rotation_config = new
.failure_threshold
.backoff_duration
.max_backoff_duration
.health_check_interval
.health_check_timeout
.enabled;
// Create rotator and add proxies
let rotator = new;
rotator.add_proxy
Middleware Chain
Compose middleware for request/response processing:
use ;
use Duration;
// Build middleware chain
let middleware = new
.rate_limiter // 10 requests per minute
.logger // Log headers, not body
.circuit_breaker // Open after 5 failures
.build;
let mut client = new.await?;
client.set_middleware;
Authentication Helpers
Built-in support for common authentication methods:
use ;
use Duration;
// Bearer token with auto-refresh
let token = with_refresh_token;
let token_manager = new
.with_refresh_url;
token_manager.set_token.await;
// Basic auth
let auth = new;
let header = auth.authorization_header; // "Basic base64(username:password)"
// Digest auth
let digest = new;
let header = digest.authorization_header;
Metrics Collection
Collect and analyze request/response metrics:
use ;
// Create metrics collector
let collector = with_max_metrics;
// Make request with timer
let mut timer = new;
timer.start_dns;
// ... DNS lookup happens ...
timer.end_dns;
timer.start_tcp;
// ... TCP connection happens ...
timer.end_tcp;
// ... rest of request ...
let metrics = RequestMetrics ;
// Record metrics
collector.record.await;
// Get statistics
let stats = collector.stats.await;
println!;
println!;
println!;
// Get percentiles
let percentiles = collector.percentiles.await;
println!;
println!;
println!;
Advanced Examples (Rust)
Example: Proxy Switching
use Client;
use Profile;
async
Example: Middleware Chain
use ;
use Profile;
use Duration;
async
Example: Metrics Collection
use ;
use Profile;
async
Example: Domain Fronting
use Profile;
async
Example: Connection Pooling
use ;
use Profile;
use Duration;
async
Project Structure
spectreq/
├── Cargo.toml # Single crate configuration
├── src/ # Main source directory
│ ├── lib.rs # Public API re-exports
│ ├── core/ # Core types and profiles
│ │ ├── profile.rs # Browser profiles
│ │ ├── tls.rs # TLS configuration
│ │ ├── tcp.rs # TCP configuration
│ │ └── error.rs # Error types
│ ├── client/ # HTTP client implementation
│ │ ├── client.rs # Main client
│ │ ├── connector.rs # HTTP connector
│ │ ├── cache.rs # HTTP caching
│ │ ├── cookies.rs # Cookie management
│ │ └── compression.rs # Decompression
│ └── py/ # Python bindings (feature-gated)
│ ├── mod.rs # Module definition
│ ├── client.rs # Python client wrapper
│ └── profile.rs # Python profile wrapper
├── spectreq-py/ # Python wrapper crate
│ └── Cargo.toml
├── examples/ # Rust examples
└── target/wheels/ # Built Python wheels
License
MIT OR Apache-2.0
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
See CONTRIBUTING.md for guidelines on:
- Pull Request Process
- Conventional Commits
- Development Setup
- Running Tests
- Code Style
Release Process
Spectre uses automated releases via GitHub Actions. Releases are triggered by version tags and are published to both Cargo (crates.io) and PyPI.
Version Management
- Version Source:
Cargo.tomlworkspace.package.version is the single source of truth - Python Version:
pyproject.tomlversion is automatically synced via script - Versioning: Semantic Versioning (SemVer) - https://semver.org/
- Changelog: CHANGELOG.md follows Keep a Changelog format
Creating a Release
Automated Release (Recommended)
Using cargo-release:
# 1. Ensure Conventional Commits in your PRs
# (Used for automated changelog generation)
# 2. Update CHANGELOG.md with new entries
# Add features, bug fixes, breaking changes under [Unreleased]
# 3. Run release prep (creates a commit with version bump)
# 4. Push the commit
# 5. Create and push the tag (triggers CI)
Manual Release
# 1. Update version in Cargo.toml
# Edit workspace.package.version
# 2. Sync version to pyproject.toml
# 3. Update CHANGELOG.md
# - Move entries from [Unreleased] to new version section
# - Add release date
# - Update comparison links at bottom
# 4. Run pre-release checks
# 5. Commit and tag
# 6. Push to trigger CI
What Happens During Release
When you push a version tag (e.g., v0.2.0), the GitHub Actions workflow:
- Verification: Checks version consistency (Cargo.toml, pyproject.toml, tag)
- Testing: Runs full test suite on Linux, macOS, Windows
- Build:
- Builds Rust crates
- Builds Python wheels via cibuildwheel (manylinux, musllinux, macOS, Windows)
- Builds source distribution
- Publish: Simultaneously publishes to:
- Cargo (crates.io): spectreq, spectreq, spectreq-py
- PyPI: All wheels + sdist for
spectreq-pypackage
- Release: Creates GitHub Release with changelog entries
Release Artifacts
| Artifact | Location | Description |
|---|---|---|
spectreq |
https://crates.io/crates/spectreq-core | Core Rust crate |
spectreq |
https://crates.io/crates/spectreq-client | Client Rust crate |
spectreq-py |
https://crates.io/crates/spectreq-py | Python bindings Rust crate |
spectre |
https://pypi.org/project/spectreq/ | Python package (wheels) |
Pre-release Checklist
Before creating a release:
- All tests pass (
cargo test --workspaceandpytest) - CHANGELOG.md is updated with all changes
- Version is incremented correctly (MAJOR.MINOR.PATCH)
- Breaking changes are documented in CHANGELOG.md
-
scripts/pre-release-check.shpasses - Dependencies are up to date
Yanking Releases
If a critical issue is found after release:
Cargo (crates.io):
# To unyank (if issue is fixed):
PyPI:
# To unyank:
Note: Yanking should be done within 24 hours of release to minimize impact.
Testing Before Release
To test the release process without actually publishing:
# Test PyPI publish workflow
# This builds the wheel and publishes to TestPyPI
# You can then test install from TestPyPI before the real release
Version Bumping Guide
| Change Type | Bump | Example |
|---|---|---|
| Bug fix | PATCH | 0.1.0 → 0.1.1 |
| New feature (backwards compatible) | MINOR | 0.1.0 → 0.2.0 |
| Breaking change | MAJOR | 0.1.0 → 1.0.0 |
For 0.x versions:
- Breaking changes increment MINOR (signals stability intent)
- Non-breaking features/fixes increment PATCH
See Also
- Examples - Example scripts demonstrating Spectre usage
- JA4 TLS Fingerprinting
- HTTP/2 Specification
- RFC 7234 - HTTP Caching