fasthttpc 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fasthttpc-0.6.0/LICENSE +21 -0
- fasthttpc-0.6.0/PKG-INFO +232 -0
- fasthttpc-0.6.0/README.md +166 -0
- fasthttpc-0.6.0/fasthttpc/__init__.py +102 -0
- fasthttpc-0.6.0/fasthttpc/_api.py +272 -0
- fasthttpc-0.6.0/fasthttpc/_backend.py +589 -0
- fasthttpc-0.6.0/fasthttpc/_log.py +40 -0
- fasthttpc-0.6.0/fasthttpc/async_session.py +1724 -0
- fasthttpc-0.6.0/fasthttpc/auth.py +328 -0
- fasthttpc-0.6.0/fasthttpc/buffer.py +137 -0
- fasthttpc-0.6.0/fasthttpc/cache.py +151 -0
- fasthttpc-0.6.0/fasthttpc/config.py +207 -0
- fasthttpc-0.6.0/fasthttpc/cookies.py +186 -0
- fasthttpc-0.6.0/fasthttpc/crypto_math.py +202 -0
- fasthttpc-0.6.0/fasthttpc/fingerprint.py +768 -0
- fasthttpc-0.6.0/fasthttpc/http3/__init__.py +18 -0
- fasthttpc-0.6.0/fasthttpc/http3/altsvc.py +115 -0
- fasthttpc-0.6.0/fasthttpc/http3/async_client.py +234 -0
- fasthttpc-0.6.0/fasthttpc/http3/core.py +276 -0
- fasthttpc-0.6.0/fasthttpc/http3/fingerprint.py +95 -0
- fasthttpc-0.6.0/fasthttpc/http3/manager.py +199 -0
- fasthttpc-0.6.0/fasthttpc/http3/options.py +37 -0
- fasthttpc-0.6.0/fasthttpc/http3/sync_client.py +174 -0
- fasthttpc-0.6.0/fasthttpc/http3/verify.py +21 -0
- fasthttpc-0.6.0/fasthttpc/metrics.py +108 -0
- fasthttpc-0.6.0/fasthttpc/models/__init__.py +0 -0
- fasthttpc-0.6.0/fasthttpc/models/headers.py +109 -0
- fasthttpc-0.6.0/fasthttpc/models/request.py +100 -0
- fasthttpc-0.6.0/fasthttpc/models/response.py +558 -0
- fasthttpc-0.6.0/fasthttpc/models/urls.py +104 -0
- fasthttpc-0.6.0/fasthttpc/multipart.py +119 -0
- fasthttpc-0.6.0/fasthttpc/plugins.py +146 -0
- fasthttpc-0.6.0/fasthttpc/protocol/__init__.py +0 -0
- fasthttpc-0.6.0/fasthttpc/protocol/async_h2.py +774 -0
- fasthttpc-0.6.0/fasthttpc/protocol/dns_over_https.py +202 -0
- fasthttpc-0.6.0/fasthttpc/protocol/http1_parser.py +190 -0
- fasthttpc-0.6.0/fasthttpc/protocol/http2_parser.py +1753 -0
- fasthttpc-0.6.0/fasthttpc/py.typed +0 -0
- fasthttpc-0.6.0/fasthttpc/retry.py +156 -0
- fasthttpc-0.6.0/fasthttpc/security/__init__.py +0 -0
- fasthttpc-0.6.0/fasthttpc/security/alerts.py +39 -0
- fasthttpc-0.6.0/fasthttpc/security/cert_validator.py +441 -0
- fasthttpc-0.6.0/fasthttpc/security/client_cert.py +344 -0
- fasthttpc-0.6.0/fasthttpc/security/keyshare.py +265 -0
- fasthttpc-0.6.0/fasthttpc/security/mtls.py +282 -0
- fasthttpc-0.6.0/fasthttpc/security/session_tickets.py +466 -0
- fasthttpc-0.6.0/fasthttpc/security/tls12.py +1435 -0
- fasthttpc-0.6.0/fasthttpc/security/tls12_legacy.py +299 -0
- fasthttpc-0.6.0/fasthttpc/security/tls_adapter.py +1111 -0
- fasthttpc-0.6.0/fasthttpc/session.py +1372 -0
- fasthttpc-0.6.0/fasthttpc/streaming.py +218 -0
- fasthttpc-0.6.0/fasthttpc/timeout.py +9 -0
- fasthttpc-0.6.0/fasthttpc/tls13/__init__.py +26 -0
- fasthttpc-0.6.0/fasthttpc/tls13/_compat.py +216 -0
- fasthttpc-0.6.0/fasthttpc/tls13/_records.py +35 -0
- fasthttpc-0.6.0/fasthttpc/tls13/async_stream.py +173 -0
- fasthttpc-0.6.0/fasthttpc/tls13/connection.py +833 -0
- fasthttpc-0.6.0/fasthttpc/tls13/errors.py +22 -0
- fasthttpc-0.6.0/fasthttpc/tls13/events.py +57 -0
- fasthttpc-0.6.0/fasthttpc/tls13/sync_socket.py +102 -0
- fasthttpc-0.6.0/fasthttpc/tls_crafter.py +523 -0
- fasthttpc-0.6.0/fasthttpc/tls_tools.py +623 -0
- fasthttpc-0.6.0/fasthttpc/transport/__init__.py +0 -0
- fasthttpc-0.6.0/fasthttpc/transport/connection_pool.py +366 -0
- fasthttpc-0.6.0/fasthttpc/transport/happy_eyeballs.py +144 -0
- fasthttpc-0.6.0/fasthttpc/transport/lingering.py +50 -0
- fasthttpc-0.6.0/fasthttpc/transport/mock.py +83 -0
- fasthttpc-0.6.0/fasthttpc/transport/proxy.py +410 -0
- fasthttpc-0.6.0/fasthttpc.egg-info/PKG-INFO +232 -0
- fasthttpc-0.6.0/fasthttpc.egg-info/SOURCES.txt +133 -0
- fasthttpc-0.6.0/fasthttpc.egg-info/dependency_links.txt +1 -0
- fasthttpc-0.6.0/fasthttpc.egg-info/requires.txt +42 -0
- fasthttpc-0.6.0/fasthttpc.egg-info/top_level.txt +1 -0
- fasthttpc-0.6.0/pyproject.toml +103 -0
- fasthttpc-0.6.0/setup.cfg +4 -0
- fasthttpc-0.6.0/tests/test_api_matrix.py +151 -0
- fasthttpc-0.6.0/tests/test_async_api_parity.py +195 -0
- fasthttpc-0.6.0/tests/test_async_h2.py +923 -0
- fasthttpc-0.6.0/tests/test_async_parity.py +331 -0
- fasthttpc-0.6.0/tests/test_async_pool.py +459 -0
- fasthttpc-0.6.0/tests/test_async_ws.py +279 -0
- fasthttpc-0.6.0/tests/test_auth.py +423 -0
- fasthttpc-0.6.0/tests/test_backend_trio.py +706 -0
- fasthttpc-0.6.0/tests/test_certificate_verify.py +175 -0
- fasthttpc-0.6.0/tests/test_compat_versions.py +106 -0
- fasthttpc-0.6.0/tests/test_config.py +165 -0
- fasthttpc-0.6.0/tests/test_cookies.py +98 -0
- fasthttpc-0.6.0/tests/test_duzelt_regresyon.py +67 -0
- fasthttpc-0.6.0/tests/test_elapsed_clock.py +47 -0
- fasthttpc-0.6.0/tests/test_error_handling.py +84 -0
- fasthttpc-0.6.0/tests/test_fingerprint.py +143 -0
- fasthttpc-0.6.0/tests/test_handshake.py +257 -0
- fasthttpc-0.6.0/tests/test_happy_eyeballs.py +220 -0
- fasthttpc-0.6.0/tests/test_hooks_plugins.py +243 -0
- fasthttpc-0.6.0/tests/test_hpack.py +190 -0
- fasthttpc-0.6.0/tests/test_hrr_keyshare.py +238 -0
- fasthttpc-0.6.0/tests/test_http2.py +333 -0
- fasthttpc-0.6.0/tests/test_http3.py +412 -0
- fasthttpc-0.6.0/tests/test_interop_faults.py +191 -0
- fasthttpc-0.6.0/tests/test_interop_openssl.py +481 -0
- fasthttpc-0.6.0/tests/test_interop_tls12.py +116 -0
- fasthttpc-0.6.0/tests/test_interop_tlslite.py +145 -0
- fasthttpc-0.6.0/tests/test_interop_windows_yardimcilari.py +38 -0
- fasthttpc-0.6.0/tests/test_key_schedule.py +139 -0
- fasthttpc-0.6.0/tests/test_legacy_tls.py +503 -0
- fasthttpc-0.6.0/tests/test_mock_transport.py +160 -0
- fasthttpc-0.6.0/tests/test_models.py +90 -0
- fasthttpc-0.6.0/tests/test_mtls_fake.py +490 -0
- fasthttpc-0.6.0/tests/test_mtls_interop.py +207 -0
- fasthttpc-0.6.0/tests/test_mtls_stdlib_server.py +161 -0
- fasthttpc-0.6.0/tests/test_mtls_unit.py +403 -0
- fasthttpc-0.6.0/tests/test_parmakizi_profilleri.py +431 -0
- fasthttpc-0.6.0/tests/test_profile_headers.py +261 -0
- fasthttpc-0.6.0/tests/test_proxy.py +334 -0
- fasthttpc-0.6.0/tests/test_psk_resumption_async.py +339 -0
- fasthttpc-0.6.0/tests/test_psk_resumption_local.py +180 -0
- fasthttpc-0.6.0/tests/test_record_layer_perf.py +138 -0
- fasthttpc-0.6.0/tests/test_redirects.py +32 -0
- fasthttpc-0.6.0/tests/test_request_compat.py +226 -0
- fasthttpc-0.6.0/tests/test_response_compat.py +76 -0
- fasthttpc-0.6.0/tests/test_retry.py +170 -0
- fasthttpc-0.6.0/tests/test_saha_regresyon.py +207 -0
- fasthttpc-0.6.0/tests/test_session_tickets.py +142 -0
- fasthttpc-0.6.0/tests/test_streaming.py +182 -0
- fasthttpc-0.6.0/tests/test_streaming_async.py +123 -0
- fasthttpc-0.6.0/tests/test_streaming_h2.py +244 -0
- fasthttpc-0.6.0/tests/test_streaming_response.py +141 -0
- fasthttpc-0.6.0/tests/test_tls12.py +812 -0
- fasthttpc-0.6.0/tests/test_tls12_linger.py +107 -0
- fasthttpc-0.6.0/tests/test_tls13_core.py +359 -0
- fasthttpc-0.6.0/tests/test_tls13_wrappers.py +207 -0
- fasthttpc-0.6.0/tests/test_tls_record.py +186 -0
- fasthttpc-0.6.0/tests/test_trust_store_cache.py +154 -0
- fasthttpc-0.6.0/tests/test_verify_ca_path.py +98 -0
- fasthttpc-0.6.0/tests/test_websocket_handshake.py +148 -0
fasthttpc-0.6.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 fasthttpc contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
fasthttpc-0.6.0/PKG-INFO
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fasthttpc
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: Pure-Python HTTP client with browser TLS/HTTP2 fingerprint impersonation, async, HTTP/2 and TLS 1.3/1.2
|
|
5
|
+
Author: Buğra
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/bu-ra34/fasthttpc
|
|
8
|
+
Project-URL: Documentation, https://bu-ra34.github.io/fasthttpc/
|
|
9
|
+
Project-URL: Repository, https://github.com/bu-ra34/fasthttpc
|
|
10
|
+
Project-URL: Issues, https://github.com/bu-ra34/fasthttpc/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/bu-ra34/fasthttpc/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: http,http-client,http2,tls,tls13,ja3,ja4,fingerprint,impersonate,async,asyncio,requests,httpx,pure-python
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Framework :: AsyncIO
|
|
23
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
25
|
+
Classifier: Topic :: Security :: Cryptography
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Requires-Dist: cryptography>=41.0
|
|
31
|
+
Requires-Dist: certifi>=2023.7.22
|
|
32
|
+
Provides-Extra: brotli
|
|
33
|
+
Requires-Dist: brotli>=1.0; extra == "brotli"
|
|
34
|
+
Provides-Extra: zstd
|
|
35
|
+
Requires-Dist: zstandard>=0.21; extra == "zstd"
|
|
36
|
+
Provides-Extra: http3
|
|
37
|
+
Requires-Dist: aioquic>=1.3; extra == "http3"
|
|
38
|
+
Provides-Extra: trio
|
|
39
|
+
Requires-Dist: anyio>=4.0; extra == "trio"
|
|
40
|
+
Requires-Dist: trio>=0.22; extra == "trio"
|
|
41
|
+
Provides-Extra: docs
|
|
42
|
+
Requires-Dist: mkdocs>=1.6; extra == "docs"
|
|
43
|
+
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
|
|
44
|
+
Requires-Dist: mkdocstrings[python]>=0.26; extra == "docs"
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
47
|
+
Requires-Dist: h2>=4; extra == "dev"
|
|
48
|
+
Requires-Dist: tlslite-ng>=0.8; extra == "dev"
|
|
49
|
+
Requires-Dist: brotli>=1.0; extra == "dev"
|
|
50
|
+
Requires-Dist: aioquic>=1.3; extra == "dev"
|
|
51
|
+
Requires-Dist: anyio>=4.0; extra == "dev"
|
|
52
|
+
Requires-Dist: trio>=0.22; extra == "dev"
|
|
53
|
+
Requires-Dist: requests; extra == "dev"
|
|
54
|
+
Requires-Dist: httpx; extra == "dev"
|
|
55
|
+
Requires-Dist: ruff; extra == "dev"
|
|
56
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
57
|
+
Requires-Dist: build; extra == "dev"
|
|
58
|
+
Requires-Dist: twine; extra == "dev"
|
|
59
|
+
Provides-Extra: all
|
|
60
|
+
Requires-Dist: brotli>=1.0; extra == "all"
|
|
61
|
+
Requires-Dist: zstandard>=0.21; extra == "all"
|
|
62
|
+
Requires-Dist: aioquic>=1.3; extra == "all"
|
|
63
|
+
Requires-Dist: anyio>=4.0; extra == "all"
|
|
64
|
+
Requires-Dist: trio>=0.22; extra == "all"
|
|
65
|
+
Dynamic: license-file
|
|
66
|
+
|
|
67
|
+
# fasthttpc
|
|
68
|
+
|
|
69
|
+
[](https://github.com/bu-ra34/fasthttpc/actions/workflows/ci.yml)
|
|
70
|
+
[](https://pypi.org/project/fasthttpc/)
|
|
71
|
+
[](https://pypi.org/project/fasthttpc/)
|
|
72
|
+
[](LICENSE)
|
|
73
|
+
[](https://bu-ra34.github.io/fasthttpc/)
|
|
74
|
+
|
|
75
|
+
[English](README.md) | [Türkçe](README.tr.md)
|
|
76
|
+
|
|
77
|
+
A pure-Python HTTP client with its own TLS 1.3 / TLS 1.2 stack, browser
|
|
78
|
+
TLS and HTTP/2 fingerprint impersonation (Chrome, Firefox, Safari), HTTP/2
|
|
79
|
+
multiplexing, and a synchronous and an asyncio API. No C extension of its own:
|
|
80
|
+
the only compiled dependency is [`cryptography`](https://cryptography.io) for
|
|
81
|
+
primitives (AEAD, X25519, certificate parsing).
|
|
82
|
+
|
|
83
|
+
> **Status: experimental (alpha).** The TLS stack is written from scratch and
|
|
84
|
+
> has **not** been independently security-audited. For critical production
|
|
85
|
+
> traffic prefer a mature client such as `curl_cffi`, `httpx` or `requests`.
|
|
86
|
+
> See [Security model](#security-model) and [Known limits](#known-limits).
|
|
87
|
+
|
|
88
|
+
## Install
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pip install fasthttpc
|
|
92
|
+
pip install "fasthttpc[brotli,zstd]" # optional content decoders
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Python 3.10 - 3.13 on Linux, macOS and Windows.
|
|
96
|
+
|
|
97
|
+
## Quick start
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from fasthttpc import Session
|
|
101
|
+
|
|
102
|
+
with Session(impersonate="chrome_131") as s:
|
|
103
|
+
r = s.get("https://httpbin.org/get")
|
|
104
|
+
print(r.status_code, r.elapsed)
|
|
105
|
+
print(r.json())
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Async:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import asyncio
|
|
112
|
+
from fasthttpc import AsyncSession
|
|
113
|
+
|
|
114
|
+
async def main():
|
|
115
|
+
async with AsyncSession(impersonate="chrome_131") as s:
|
|
116
|
+
rs = await asyncio.gather(*(s.get(f"https://httpbin.org/anything/{i}") for i in range(5)))
|
|
117
|
+
print([r.status_code for r in rs])
|
|
118
|
+
|
|
119
|
+
asyncio.run(main())
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Offline testing:
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
from fasthttpc import Session, Response, MockTransport
|
|
126
|
+
|
|
127
|
+
transport = MockTransport(lambda request: Response(200, body=b'{"ok": true}',
|
|
128
|
+
headers={"Content-Type": "application/json"}))
|
|
129
|
+
with Session(transport=transport) as s:
|
|
130
|
+
assert s.get("https://api.example.com/").json() == {"ok": True}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Features
|
|
134
|
+
|
|
135
|
+
| Area | Support |
|
|
136
|
+
|---|---|
|
|
137
|
+
| Protocols | HTTP/1.1 (keep-alive, chunked), HTTP/2 (multiplexing, flow control, GOAWAY), WebSocket (`ws://`, `wss://`) |
|
|
138
|
+
| TLS | Own TLS 1.3 (HelloRetryRequest, key_share x25519/secp256r1/secp384r1) and a safe subset of TLS 1.2 (ECDHE + AEAD, EMS required) |
|
|
139
|
+
| Server authentication | Chain + hostname, CertificateVerify, Finished, all mandatory; `verify=` custom CA bundle |
|
|
140
|
+
| Fingerprints | `chrome_131`, `firefox_133`, `safari_18` profiles: ClientHello (JA3/JA4), HTTP/2 SETTINGS, pseudo-header order, header order |
|
|
141
|
+
| Async | `AsyncSession` with the same fingerprinting and real HTTP/2 multiplexing |
|
|
142
|
+
| Proxies | HTTP CONNECT (+Basic), SOCKS5 (RFC 1929), rotation; TLS always terminates inside the tunnel |
|
|
143
|
+
| Timeouts / limits / retries | `Timeout`, `Limits`, urllib3-style `Retry` with `Retry-After` |
|
|
144
|
+
| Cookies, cache, redirects | RFC 6265 cookie jar, response cache, redirect history |
|
|
145
|
+
| DNS | Optional DNS-over-HTTPS resolver |
|
|
146
|
+
| Testing | `MockTransport` (sync and async handlers) |
|
|
147
|
+
| Typing | Ships `py.typed` |
|
|
148
|
+
|
|
149
|
+
## How it compares
|
|
150
|
+
|
|
151
|
+
Honest comparison; "maturity" matters as much as features here.
|
|
152
|
+
|
|
153
|
+
| | fasthttpc | requests | httpx | curl_cffi |
|
|
154
|
+
|---|---|---|---|---|
|
|
155
|
+
| Implementation | Pure Python + `cryptography` | Pure Python + urllib3 + `ssl` | Pure Python + h11/h2 + `ssl` | libcurl-impersonate (C) via cffi |
|
|
156
|
+
| TLS library | **Own TLS 1.3/1.2 code** | OpenSSL via `ssl` | OpenSSL via `ssl` | BoringSSL |
|
|
157
|
+
| Browser TLS/JA3/JA4 impersonation | Yes (3 families) | No | No | Yes (many versions, best coverage) |
|
|
158
|
+
| HTTP/2 fingerprint | Yes | No | No | Yes |
|
|
159
|
+
| HTTP/2 | Yes | No | Yes | Yes |
|
|
160
|
+
| HTTP/3 | Not yet | No | No | Yes |
|
|
161
|
+
| Async | Yes (asyncio) | No | Yes (asyncio, trio via anyio) | Yes |
|
|
162
|
+
| `verify=False` | **Not supported by design** | Yes | Yes | Yes |
|
|
163
|
+
| Session resumption / 0-RTT | No | Yes (OpenSSL) | Yes (OpenSSL) | Yes |
|
|
164
|
+
| Post-quantum key exchange | No | via OpenSSL 3.5+ | via OpenSSL 3.5+ | Yes |
|
|
165
|
+
| Maturity / production use | **Alpha, young, no external audit** | Very mature | Mature | Mature |
|
|
166
|
+
| Years of real-world hardening | None | >10 | >5 | Several |
|
|
167
|
+
| Speed | Pure Python: slower on bulk transfers | Fast enough | Fast enough | Fastest |
|
|
168
|
+
|
|
169
|
+
Choose fasthttpc if you want a dependency-light, readable, inspectable client
|
|
170
|
+
whose TLS fingerprint you can control precisely, or you cannot ship C
|
|
171
|
+
extensions. Choose `curl_cffi` if you need the widest and most up-to-date
|
|
172
|
+
fingerprint coverage or maximum performance. Choose `requests`/`httpx` when
|
|
173
|
+
you do not need impersonation.
|
|
174
|
+
|
|
175
|
+
## Security model
|
|
176
|
+
|
|
177
|
+
Every TLS 1.3 connection authenticates the server with three independent
|
|
178
|
+
checks, all mandatory:
|
|
179
|
+
|
|
180
|
+
| Check | What it proves |
|
|
181
|
+
|---|---|
|
|
182
|
+
| Certificate chain | A trusted CA signed the certificate, hostname matches, validity period |
|
|
183
|
+
| **CertificateVerify** | The peer holds the certificate's **private key** (RFC 8446 section 4.4.3) |
|
|
184
|
+
| **Server Finished** | The handshake transcript was not tampered with (section 4.4.4) |
|
|
185
|
+
|
|
186
|
+
Trust anchors are the `certifi` bundle plus the system store, or exactly the
|
|
187
|
+
PEM file you pass as `verify="ca.pem"`. **`verify=False` is not supported** and
|
|
188
|
+
raises `ValueError`; pass the CA (or the self-signed certificate) you want to
|
|
189
|
+
trust instead. TLS 1.2 additionally enforces Extended Master Secret,
|
|
190
|
+
renegotiation_info, `DOWNGRD` sentinel detection and rejects CBC, static RSA,
|
|
191
|
+
DHE and SHA-1 signatures.
|
|
192
|
+
|
|
193
|
+
What this does **not** give you: an independent audit, constant-time
|
|
194
|
+
guarantees beyond what `cryptography` provides, or protection from
|
|
195
|
+
implementation bugs in a young protocol stack. Report vulnerabilities privately
|
|
196
|
+
via GitHub security advisories.
|
|
197
|
+
|
|
198
|
+
## Known limits
|
|
199
|
+
|
|
200
|
+
- No session resumption (PSK) and no 0-RTT: every connection does a full handshake.
|
|
201
|
+
- No post-quantum / hybrid key shares (X25519MLKEM768), no secp521r1/ffdhe.
|
|
202
|
+
- TLS 1.2: only ECDHE + AES-GCM / ChaCha20-Poly1305; CBC and older suites are rejected with an explicit error.
|
|
203
|
+
- HPACK Huffman *encoding* is not implemented (decoding is); this causes a tiny HTTP/2 fingerprint deviation.
|
|
204
|
+
- HTTP/2 server push is a protocol error (`ENABLE_PUSH=0`); PRIORITY is not sent.
|
|
205
|
+
- `Session` is not thread-safe: use one per thread.
|
|
206
|
+
- `Timeout.write` is not enforced separately on the sync side.
|
|
207
|
+
- Only 3 browser families are modelled; profiles are snapshots and age.
|
|
208
|
+
- Pure-Python crypto framing is slower than OpenSSL for large bulk transfers.
|
|
209
|
+
|
|
210
|
+
The full, detailed list is in [README.tr.md](README.tr.md) and the
|
|
211
|
+
[documentation](https://bu-ra34.github.io/fasthttpc/).
|
|
212
|
+
|
|
213
|
+
## Documentation
|
|
214
|
+
|
|
215
|
+
Quick start, async usage, profiles, proxies, TLS, HTTP/2, testing, migration
|
|
216
|
+
guides and the API reference live at <https://bu-ra34.github.io/fasthttpc/>
|
|
217
|
+
(sources in [`docs/`](docs/)).
|
|
218
|
+
|
|
219
|
+
## Development
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
git clone https://github.com/bu-ra34/fasthttpc && cd fasthttpc
|
|
223
|
+
pip install -e ".[dev]"
|
|
224
|
+
pytest # offline unit tests
|
|
225
|
+
ruff check .
|
|
226
|
+
mypy
|
|
227
|
+
mkdocs serve # needs: pip install -e ".[docs]"
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## License
|
|
231
|
+
|
|
232
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# fasthttpc
|
|
2
|
+
|
|
3
|
+
[](https://github.com/bu-ra34/fasthttpc/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/fasthttpc/)
|
|
5
|
+
[](https://pypi.org/project/fasthttpc/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://bu-ra34.github.io/fasthttpc/)
|
|
8
|
+
|
|
9
|
+
[English](README.md) | [Türkçe](README.tr.md)
|
|
10
|
+
|
|
11
|
+
A pure-Python HTTP client with its own TLS 1.3 / TLS 1.2 stack, browser
|
|
12
|
+
TLS and HTTP/2 fingerprint impersonation (Chrome, Firefox, Safari), HTTP/2
|
|
13
|
+
multiplexing, and a synchronous and an asyncio API. No C extension of its own:
|
|
14
|
+
the only compiled dependency is [`cryptography`](https://cryptography.io) for
|
|
15
|
+
primitives (AEAD, X25519, certificate parsing).
|
|
16
|
+
|
|
17
|
+
> **Status: experimental (alpha).** The TLS stack is written from scratch and
|
|
18
|
+
> has **not** been independently security-audited. For critical production
|
|
19
|
+
> traffic prefer a mature client such as `curl_cffi`, `httpx` or `requests`.
|
|
20
|
+
> See [Security model](#security-model) and [Known limits](#known-limits).
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install fasthttpc
|
|
26
|
+
pip install "fasthttpc[brotli,zstd]" # optional content decoders
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Python 3.10 - 3.13 on Linux, macOS and Windows.
|
|
30
|
+
|
|
31
|
+
## Quick start
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from fasthttpc import Session
|
|
35
|
+
|
|
36
|
+
with Session(impersonate="chrome_131") as s:
|
|
37
|
+
r = s.get("https://httpbin.org/get")
|
|
38
|
+
print(r.status_code, r.elapsed)
|
|
39
|
+
print(r.json())
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Async:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
import asyncio
|
|
46
|
+
from fasthttpc import AsyncSession
|
|
47
|
+
|
|
48
|
+
async def main():
|
|
49
|
+
async with AsyncSession(impersonate="chrome_131") as s:
|
|
50
|
+
rs = await asyncio.gather(*(s.get(f"https://httpbin.org/anything/{i}") for i in range(5)))
|
|
51
|
+
print([r.status_code for r in rs])
|
|
52
|
+
|
|
53
|
+
asyncio.run(main())
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Offline testing:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from fasthttpc import Session, Response, MockTransport
|
|
60
|
+
|
|
61
|
+
transport = MockTransport(lambda request: Response(200, body=b'{"ok": true}',
|
|
62
|
+
headers={"Content-Type": "application/json"}))
|
|
63
|
+
with Session(transport=transport) as s:
|
|
64
|
+
assert s.get("https://api.example.com/").json() == {"ok": True}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Features
|
|
68
|
+
|
|
69
|
+
| Area | Support |
|
|
70
|
+
|---|---|
|
|
71
|
+
| Protocols | HTTP/1.1 (keep-alive, chunked), HTTP/2 (multiplexing, flow control, GOAWAY), WebSocket (`ws://`, `wss://`) |
|
|
72
|
+
| TLS | Own TLS 1.3 (HelloRetryRequest, key_share x25519/secp256r1/secp384r1) and a safe subset of TLS 1.2 (ECDHE + AEAD, EMS required) |
|
|
73
|
+
| Server authentication | Chain + hostname, CertificateVerify, Finished, all mandatory; `verify=` custom CA bundle |
|
|
74
|
+
| Fingerprints | `chrome_131`, `firefox_133`, `safari_18` profiles: ClientHello (JA3/JA4), HTTP/2 SETTINGS, pseudo-header order, header order |
|
|
75
|
+
| Async | `AsyncSession` with the same fingerprinting and real HTTP/2 multiplexing |
|
|
76
|
+
| Proxies | HTTP CONNECT (+Basic), SOCKS5 (RFC 1929), rotation; TLS always terminates inside the tunnel |
|
|
77
|
+
| Timeouts / limits / retries | `Timeout`, `Limits`, urllib3-style `Retry` with `Retry-After` |
|
|
78
|
+
| Cookies, cache, redirects | RFC 6265 cookie jar, response cache, redirect history |
|
|
79
|
+
| DNS | Optional DNS-over-HTTPS resolver |
|
|
80
|
+
| Testing | `MockTransport` (sync and async handlers) |
|
|
81
|
+
| Typing | Ships `py.typed` |
|
|
82
|
+
|
|
83
|
+
## How it compares
|
|
84
|
+
|
|
85
|
+
Honest comparison; "maturity" matters as much as features here.
|
|
86
|
+
|
|
87
|
+
| | fasthttpc | requests | httpx | curl_cffi |
|
|
88
|
+
|---|---|---|---|---|
|
|
89
|
+
| Implementation | Pure Python + `cryptography` | Pure Python + urllib3 + `ssl` | Pure Python + h11/h2 + `ssl` | libcurl-impersonate (C) via cffi |
|
|
90
|
+
| TLS library | **Own TLS 1.3/1.2 code** | OpenSSL via `ssl` | OpenSSL via `ssl` | BoringSSL |
|
|
91
|
+
| Browser TLS/JA3/JA4 impersonation | Yes (3 families) | No | No | Yes (many versions, best coverage) |
|
|
92
|
+
| HTTP/2 fingerprint | Yes | No | No | Yes |
|
|
93
|
+
| HTTP/2 | Yes | No | Yes | Yes |
|
|
94
|
+
| HTTP/3 | Not yet | No | No | Yes |
|
|
95
|
+
| Async | Yes (asyncio) | No | Yes (asyncio, trio via anyio) | Yes |
|
|
96
|
+
| `verify=False` | **Not supported by design** | Yes | Yes | Yes |
|
|
97
|
+
| Session resumption / 0-RTT | No | Yes (OpenSSL) | Yes (OpenSSL) | Yes |
|
|
98
|
+
| Post-quantum key exchange | No | via OpenSSL 3.5+ | via OpenSSL 3.5+ | Yes |
|
|
99
|
+
| Maturity / production use | **Alpha, young, no external audit** | Very mature | Mature | Mature |
|
|
100
|
+
| Years of real-world hardening | None | >10 | >5 | Several |
|
|
101
|
+
| Speed | Pure Python: slower on bulk transfers | Fast enough | Fast enough | Fastest |
|
|
102
|
+
|
|
103
|
+
Choose fasthttpc if you want a dependency-light, readable, inspectable client
|
|
104
|
+
whose TLS fingerprint you can control precisely, or you cannot ship C
|
|
105
|
+
extensions. Choose `curl_cffi` if you need the widest and most up-to-date
|
|
106
|
+
fingerprint coverage or maximum performance. Choose `requests`/`httpx` when
|
|
107
|
+
you do not need impersonation.
|
|
108
|
+
|
|
109
|
+
## Security model
|
|
110
|
+
|
|
111
|
+
Every TLS 1.3 connection authenticates the server with three independent
|
|
112
|
+
checks, all mandatory:
|
|
113
|
+
|
|
114
|
+
| Check | What it proves |
|
|
115
|
+
|---|---|
|
|
116
|
+
| Certificate chain | A trusted CA signed the certificate, hostname matches, validity period |
|
|
117
|
+
| **CertificateVerify** | The peer holds the certificate's **private key** (RFC 8446 section 4.4.3) |
|
|
118
|
+
| **Server Finished** | The handshake transcript was not tampered with (section 4.4.4) |
|
|
119
|
+
|
|
120
|
+
Trust anchors are the `certifi` bundle plus the system store, or exactly the
|
|
121
|
+
PEM file you pass as `verify="ca.pem"`. **`verify=False` is not supported** and
|
|
122
|
+
raises `ValueError`; pass the CA (or the self-signed certificate) you want to
|
|
123
|
+
trust instead. TLS 1.2 additionally enforces Extended Master Secret,
|
|
124
|
+
renegotiation_info, `DOWNGRD` sentinel detection and rejects CBC, static RSA,
|
|
125
|
+
DHE and SHA-1 signatures.
|
|
126
|
+
|
|
127
|
+
What this does **not** give you: an independent audit, constant-time
|
|
128
|
+
guarantees beyond what `cryptography` provides, or protection from
|
|
129
|
+
implementation bugs in a young protocol stack. Report vulnerabilities privately
|
|
130
|
+
via GitHub security advisories.
|
|
131
|
+
|
|
132
|
+
## Known limits
|
|
133
|
+
|
|
134
|
+
- No session resumption (PSK) and no 0-RTT: every connection does a full handshake.
|
|
135
|
+
- No post-quantum / hybrid key shares (X25519MLKEM768), no secp521r1/ffdhe.
|
|
136
|
+
- TLS 1.2: only ECDHE + AES-GCM / ChaCha20-Poly1305; CBC and older suites are rejected with an explicit error.
|
|
137
|
+
- HPACK Huffman *encoding* is not implemented (decoding is); this causes a tiny HTTP/2 fingerprint deviation.
|
|
138
|
+
- HTTP/2 server push is a protocol error (`ENABLE_PUSH=0`); PRIORITY is not sent.
|
|
139
|
+
- `Session` is not thread-safe: use one per thread.
|
|
140
|
+
- `Timeout.write` is not enforced separately on the sync side.
|
|
141
|
+
- Only 3 browser families are modelled; profiles are snapshots and age.
|
|
142
|
+
- Pure-Python crypto framing is slower than OpenSSL for large bulk transfers.
|
|
143
|
+
|
|
144
|
+
The full, detailed list is in [README.tr.md](README.tr.md) and the
|
|
145
|
+
[documentation](https://bu-ra34.github.io/fasthttpc/).
|
|
146
|
+
|
|
147
|
+
## Documentation
|
|
148
|
+
|
|
149
|
+
Quick start, async usage, profiles, proxies, TLS, HTTP/2, testing, migration
|
|
150
|
+
guides and the API reference live at <https://bu-ra34.github.io/fasthttpc/>
|
|
151
|
+
(sources in [`docs/`](docs/)).
|
|
152
|
+
|
|
153
|
+
## Development
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
git clone https://github.com/bu-ra34/fasthttpc && cd fasthttpc
|
|
157
|
+
pip install -e ".[dev]"
|
|
158
|
+
pytest # offline unit tests
|
|
159
|
+
ruff check .
|
|
160
|
+
mypy
|
|
161
|
+
mkdocs serve # needs: pip install -e ".[docs]"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""
|
|
2
|
+
fasthttpc — Pure-Python HTTP istemcisi
|
|
3
|
+
|
|
4
|
+
TLS 1.3 fingerprinting, Chrome/Firefox/Safari impersonation,
|
|
5
|
+
async destek, akıllı connection pool ve plugin sistemi içerir.
|
|
6
|
+
|
|
7
|
+
Hızlı başlangıç::
|
|
8
|
+
|
|
9
|
+
from fasthttpc import Session, Timeout
|
|
10
|
+
|
|
11
|
+
with Session(impersonate="chrome_131") as s:
|
|
12
|
+
r = s.get("https://httpbin.org/get")
|
|
13
|
+
print(r.status_code, r.elapsed)
|
|
14
|
+
|
|
15
|
+
Async::
|
|
16
|
+
|
|
17
|
+
from fasthttpc import AsyncSession
|
|
18
|
+
|
|
19
|
+
async with AsyncSession() as s:
|
|
20
|
+
r = await s.get("https://httpbin.org/get")
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
# `cryptography` alt modülleri import edilmeden ÖNCE ayarlanmalı. Bazı
|
|
24
|
+
# ortamlarda (özellikle Pydroid3/Android'deki OpenSSL 3.0) legacy provider
|
|
25
|
+
# yüklenemez ve import ölümcül bir RuntimeError ile patlar. fasthttpc yalnızca
|
|
26
|
+
# modern algoritmalar kullanır (AES-GCM, ChaCha20-Poly1305, x25519, ECDSA,
|
|
27
|
+
# RSA-PSS, Ed25519) — hiçbiri legacy provider'a ihtiyaç duymaz, dolayısıyla
|
|
28
|
+
# onu devre dışı bırakmak güvenli ve gereklidir.
|
|
29
|
+
import os as _os
|
|
30
|
+
_os.environ.setdefault("CRYPTOGRAPHY_OPENSSL_NO_LEGACY", "1")
|
|
31
|
+
|
|
32
|
+
from .session import Session
|
|
33
|
+
from .async_session import AsyncSession
|
|
34
|
+
from .config import Timeout, Limits
|
|
35
|
+
from .retry import Retry
|
|
36
|
+
from .transport.mock import MockTransport, BaseTransport
|
|
37
|
+
from .multipart import encode_multipart
|
|
38
|
+
from .models.response import Response, HTTPStatusError
|
|
39
|
+
from .models.request import Request
|
|
40
|
+
from .models.headers import Headers
|
|
41
|
+
from .models.urls import URL
|
|
42
|
+
from .cache import ResponseCache
|
|
43
|
+
from .cookies import CookieJar, Cookie
|
|
44
|
+
from ._log import enable_debug_logging
|
|
45
|
+
from .protocol.dns_over_https import DoHResolver
|
|
46
|
+
from .fingerprint import (
|
|
47
|
+
get_profile,
|
|
48
|
+
available_profiles,
|
|
49
|
+
ja3_from_client_hello,
|
|
50
|
+
ja3_for_profile,
|
|
51
|
+
)
|
|
52
|
+
from .metrics import RequestMetrics
|
|
53
|
+
from .tls_tools import (
|
|
54
|
+
TLSFragmenter,
|
|
55
|
+
TLSDowngradeDetector,
|
|
56
|
+
ClientHelloEntropyScorer,
|
|
57
|
+
)
|
|
58
|
+
from .async_session import ProxyRotator
|
|
59
|
+
from .plugins import Plugin, RetryPlugin, LoggingPlugin, RateLimitPlugin
|
|
60
|
+
from .auth import Auth, BasicAuth, BearerAuth, DigestAuth
|
|
61
|
+
from ._api import USE_CLIENT_DEFAULT
|
|
62
|
+
|
|
63
|
+
__version__ = "0.6.0"
|
|
64
|
+
__author__ = "Buğra"
|
|
65
|
+
__all__ = [
|
|
66
|
+
"Session",
|
|
67
|
+
"AsyncSession",
|
|
68
|
+
"Timeout",
|
|
69
|
+
"Limits",
|
|
70
|
+
"Retry",
|
|
71
|
+
"MockTransport",
|
|
72
|
+
"BaseTransport",
|
|
73
|
+
"encode_multipart",
|
|
74
|
+
"Response",
|
|
75
|
+
"HTTPStatusError",
|
|
76
|
+
"Request",
|
|
77
|
+
"Headers",
|
|
78
|
+
"URL",
|
|
79
|
+
"ResponseCache",
|
|
80
|
+
"CookieJar",
|
|
81
|
+
"Cookie",
|
|
82
|
+
"DoHResolver",
|
|
83
|
+
"enable_debug_logging",
|
|
84
|
+
"get_profile",
|
|
85
|
+
"available_profiles",
|
|
86
|
+
"ja3_from_client_hello",
|
|
87
|
+
"ja3_for_profile",
|
|
88
|
+
"RequestMetrics",
|
|
89
|
+
"TLSFragmenter",
|
|
90
|
+
"TLSDowngradeDetector",
|
|
91
|
+
"ClientHelloEntropyScorer",
|
|
92
|
+
"Plugin",
|
|
93
|
+
"RetryPlugin",
|
|
94
|
+
"LoggingPlugin",
|
|
95
|
+
"RateLimitPlugin",
|
|
96
|
+
"ProxyRotator",
|
|
97
|
+
"Auth",
|
|
98
|
+
"BasicAuth",
|
|
99
|
+
"BearerAuth",
|
|
100
|
+
"DigestAuth",
|
|
101
|
+
"USE_CLIENT_DEFAULT",
|
|
102
|
+
]
|