Releases: deedy5/primp
Release list
v1.3.1
What's Changed
- fix: backport upstream bug fixes across forked crates by @deedy5 in #149
- perf: avoid Arc clones in root cert store paths and Safari emulator by @deedy5 in #150
Release v1.3.1 details
✨ Security
- fix(reqwest): Add scheme check to remove_sensitive_headers — prevents credential leakage on https→http same-host:port redirects
🐛 Fixes
- fix(h2): Backport 8 upstream fixes — missing notify_send() in set_reset, goaway stream filtering, connection flow control release after GOAWAY, guard for informational responses, dropping buffered DATA on scheduled reset, RFC 9113 idle stream frame rejection, capacity exhaustion handling
- fix(hyper): Backport 5 upstream fixes — SenderDropGuard for mid-body drop data loss, missed write wakeup deadlock in H1 dispatch, H2 capacity reservation deadlock, NO_ERROR handling in poll_trailers, 32-bit overflow in body size calculation
- fix(reqwest): Backport 3 upstream fixes — URL context in JSON decode errors, Hickory DNS init error propagation (no more panics), Google DNS fallback
- fix(primp-python): Resolve redirect race by applying policy on cloned client; RAII temp file cleanup
⚡ Performance
- perf(safari): Cache emulators per OS (iOS/macOS) to avoid Arc::make_mut deep clones on every build_safari_settings call
- perf(reqwest): default_root_store_arc() returns Arc so callers share the cached store via refcount instead of cloning
🏗️ Refactors & Chores
- chore(hyper-util): Sync upstream through v0.1.20 — modernize to std::future::poll_fn, std::task::ready, std::pin::pin!, drop futures-core dep, add RPITIT bounds, update system-configuration to ≥0.7
Full Changelog: v1.3.0...v1.3.1
v1.3.0
What's Changed
- chore: merge upstream dependency bumps and apply clippy fixes by @deedy5 in #144
- Misc fixes and refactors by @deedy5 in #145
- refactor: deduplicate browser impersonation, add H2 window update fingerprinting, clean up Python response bindings by @deedy5 in #146
- DNS resolver customization (DoH/DoT/plain), hickory-resolver 0.26 upgrade, and minor fixes by @deedy5 in #147
- perf: cache CryptoProvider/RootCertStore/BrowserEmulator, optimize Python iterators, fix Random OS consistency by @deedy5 in #148
Release v1.3.0 details
✨ Features
- DNS resolver customization — DoH, DoT, and plain DNS resolvers with Python bindings (primp-reqwest)
- Firefox WINDOW_UPDATE support — initial_stream_window_increment for HTTP/2 flow control across h2 → hyper → reqwest
- New browser profiles — Chrome 147/148, Edge 147/148, Opera 130/131; refactored impersonation infrastructure with Arc
- Cached emulators — OnceLock-cached browser emulators eliminate per-request construction overhead
- deflate field — added to BrowserSettings and apply_impersonation
🐛 Fixes
- Consistent ImpersonateOS::Random — resolved once at top of build_*_settings so User-Agent, os_platform, and sec-ch-ua-mobile all agree
- Header order & Sec-CH-UA corrections — fixed positions, grease values, brand permutations matching Chromium's GenerateBrandVersionList
- DohResolver timeout — per-query timeout prevents hang, enables ChainedResolver fallback
- WASM gating — h2-referencing code and impersonate code properly #[cfg]-gated
- Python error chains — exception messages include full source chain; non-object data sent as raw body
- max_local_error_reset_streams — wrapped in Some() for correct h2 API type
- primp-h2 clippy — replaced modulo with is_multiple_of
- primp-rustls — removed duplicate debug log in ClientHello
- Docs.rs build — excluded incompatible http3 feature, added rustc-args for reqwest_unstable
⚡ Performance
- Cache CryptoProvider and RootCertStore; Arc in OnceLock
- Eliminate recursion in os_platform/build_user_agent
- Python: cache encoding per iterator, pre-alloc buffers, eliminate headers.clone(), reduce lock scope
🔧 Upstream Merges - primp-hyper 1.8.1 → 1.9.0 (15 files, removed pin-utils, added max_local_error_reset_streams)
- primp-reqwest 0.13.2 → 0.13.3 (H3 fixes, CRL PEM parsing, debug logging)
- primp-rustls 0.23.38 → 0.23.40 (runtime FIPS detection, ECH padding fixes)
- primp-hyper-rustls 0.27.7 → 0.27.9 (removed pki-types dep, rustls-platform-verifier 0.7)
- hickory-resolver 0.25.2 → 0.26.1 (fixes NSEC3 DoS vulnerability)
🏗️ Refactors & Chores
- Python: extracted shared response/body logic into response_shared.rs (~300 lines eliminated)
- Python: replaced once_cell with std::sync::LazyLock
- MSRV bumped to 1.89.0
- CI: removed pinned maturin version, updated attest action
- Workspace-wide clippy fixes (io::Error::other(), module attributes, etc.)
Full Changelog: v1.2.3...v1.3.0
v1.2.3
v1.2.2
What's Changed
- fix(tls): GREASE improvements, Firefox/Chrome key_share fixes, ECH payload fix by @deedy5 in #135
- style+test: modernize Python type stubs & expand test coverage by @deedy5 in #136
- feat[py]: add timeouts, base_url, cookies, follow_redirects; unify Response types by @deedy5 in #137
Full Changelog: v1.2.1...v1.2.2
v1.2.1
v1.2.0
What's new in v1.2.0
-
Impersonation:
ChromeV146,EdgeV146,OperaV128/V129,SafariV26.3,FirefoxV147/V148. Random selection support (Impersonate::Chrome,::Random, etc). -
HTTP/2 fingerprinting: Custom header ordering, initial stream ID config, simplified priority settings.
-
TLS: Fixed Firefox cipher suite order, added
status_request_v2for Safari, expanded Firefox named groups. -
Python bindings:
__version__export, improved cookie/URL handling. -
Cleanup: Removed large amount of unused tests and fixtures.
-
MSRV: 1.84, license MIT, workspace resolver 3.
v1.1.3
v1.0.0
Release v1.0.0
🏗️ Custom Crates Stack
Built on custom forked crates providing full control over browser impersonation and TLS fingerprinting:
| Crate | Description | Key Components |
|---|---|---|
| primp-reqwest | HTTP client with impersonation support | Client builder, request/response handling, multipart, proxy configuration |
| primp-h2 | HTTP/2 protocol implementation | Frame handling, HPACK encoding, stream management, flow control |
| primp-hyper | HTTP client/server library | HTTP/1.1 & HTTP/2 support, body handling, connection pooling |
| primp-hyper-util | Hyper utilities | Legacy client, pool management, Tokio runtime integration |
| primp-rustls | TLS implementation with fingerprinting | TLS 1.2/1.3, certificate verification, JA3/JA4 fingerprinting |
🎭 Impersonate Profiles
Browser Profiles
| Browser | Profiles | Default |
|---|---|---|
| 🌐 Chrome | chrome_144, chrome_145 |
chrome_144 |
| 🧭 Safari | safari_18.5, safari_26 |
safari_26 |
| 🔷 Edge | edge_144, edge_145 |
edge_144 |
| 🦊 Firefox | firefox_140, firefox_146 |
firefox_146 |
| ⭕ Opera | opera_126, opera_127 |
opera_126 |
| 🎲 Random | random |
- |
OS Impersonation
| OS | Value | User-Agent Impact |
|---|---|---|
| 🤖 Android | android |
Mobile Android user-agent |
| 🍎 iOS | ios |
Mobile iOS user-agent |
| 🐧 Linux | linux |
Desktop Linux user-agent |
| 🍏 macOS | macos |
Desktop macOS user-agent |
| 🪟 Windows | windows |
Desktop Windows user-agent |
| 🎲 Random | random |
Randomly selected OS |
Usage Example
import primp
# Browser impersonation
client = primp.Client(impersonate="chrome_145", impersonate_os="windows")
# Random browser/OS
client = primp.Client(impersonate="random", impersonate_os="random")⚠️ Exception Hierarchy
Comprehensive exception hierarchy mirroring Python's requests library for familiar error handling:
RequestException (base class)
├── HTTPError # HTTP 4xx/5xx status codes
├── ConnectionError # Connection-related failures
│ ├── ConnectTimeout # Connection establishment timeout
│ ├── SSLError # SSL/TLS certificate errors
│ └── ProxyError # Proxy connection errors
├── Timeout # Timeout-related failures
│ └── ReadTimeout # Data read timeout
├── RequestError # Request building/sending errors
│ ├── InvalidURL # URL format errors
│ └── InvalidHeader # Header format errors
├── BodyError # Body-related errors
│ ├── StreamConsumedError # Stream already consumed
│ └── ChunkedEncodingError # Chunked encoding errors
├── DecodeError # Decoding errors
│ └── ContentDecodingError # Content decode errors (gzip, brotli, etc.)
├── JSONError # JSON-related errors
│ ├── InvalidJSONError # Invalid JSON in request body
│ └── JSONDecodeError # JSON decode failure in response
└── TooManyRedirects # Redirect limit exceeded
🚀 Key Features
- Async Support - Native
AsyncClientwith async/await, context managers, and concurrent requests - HTML Conversion - Convert responses to Markdown, plain text, or rich text
- Response Streaming - Memory-efficient chunk streaming and line iteration
- Cookie Management - Persistent cookie store with automatic handling
- Proxy Support - HTTP, HTTPS, SOCKS5 proxies with authentication and system proxy detection
- SSL/TLS Options - Custom CA certificates, verification controls, HTTPS-only mode
📦 Requirements
Python Support
| Version | Standard | Free-threaded |
|---|---|---|
| Python 3.10 | ✅ | - |
| Python 3.11 | ✅ | - |
| Python 3.12 | ✅ | - |
| Python 3.13 | ✅ | - |
| Python 3.14 | ✅ | ✅ |
Platform Support
Linux (glibc/manylinux)
| Architecture | Runner | Notes |
|---|---|---|
| x86_64 | ubuntu-22.04 | Primary platform |
| x86 | ubuntu-22.04 | 32-bit support |
| aarch64 | ubuntu-22.04-arm | ARM64 servers |
| armv7 | ubuntu-22.04 | ARM embedded/IoT |
| s390x | ubuntu-22.04 | IBM mainframes |
| ppc64le | ubuntu-22.04 | PowerPC servers |
Linux (musllinux)
| Architecture | Runner | Notes |
|---|---|---|
| x86_64 | ubuntu-22.04 | Alpine compatible |
| x86 | ubuntu-22.04 | 32-bit Alpine |
| aarch64 | ubuntu-22.04 | ARM64 Alpine |
| armv7 | ubuntu-22.04 | ARM Alpine |
Windows
| Architecture | Runner | Notes |
|---|---|---|
| x64 | windows-latest | Primary platform |
| x86 | windows-latest | 32-bit support |
| aarch64 | windows-11-arm | ARM64 Windows |
macOS
| Architecture | Runner | Notes |
|---|---|---|
| x86_64 | macos-15-intel | Intel Macs |
| aarch64 | macos-latest | Apple Silicon (M1/M2/M3) |
📚 Documentation
Documentation Files
| File | Description |
|---|---|
docs/README.md |
Documentation index |
docs/client.md |
Sync Client usage guide |
docs/async_client.md |
AsyncClient usage guide |
docs/response.md |
Response object reference |
docs/exceptions.md |
Exception handling guide |
Example Scripts
| Example | Description |
|---|---|
examples/basic_usage.py |
GET, POST, params, headers |
examples/async_usage.py |
Async client, concurrent requests |
examples/authentication.py |
Basic auth, bearer tokens |
examples/proxy.py |
HTTP/SOCKS5 proxies |
examples/cookies.py |
Cookie management |
examples/streaming.py |
Response streaming |
examples/post_requests.py |
POST/PUT/PATCH/DELETE |
examples/error_handling.py |
Exception handling |
examples/html_conversion.py |
HTML to text conversion |
🔧 Installation
pip install -U primp📄 License
MIT License