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.
Files changed (135) hide show
  1. fasthttpc-0.6.0/LICENSE +21 -0
  2. fasthttpc-0.6.0/PKG-INFO +232 -0
  3. fasthttpc-0.6.0/README.md +166 -0
  4. fasthttpc-0.6.0/fasthttpc/__init__.py +102 -0
  5. fasthttpc-0.6.0/fasthttpc/_api.py +272 -0
  6. fasthttpc-0.6.0/fasthttpc/_backend.py +589 -0
  7. fasthttpc-0.6.0/fasthttpc/_log.py +40 -0
  8. fasthttpc-0.6.0/fasthttpc/async_session.py +1724 -0
  9. fasthttpc-0.6.0/fasthttpc/auth.py +328 -0
  10. fasthttpc-0.6.0/fasthttpc/buffer.py +137 -0
  11. fasthttpc-0.6.0/fasthttpc/cache.py +151 -0
  12. fasthttpc-0.6.0/fasthttpc/config.py +207 -0
  13. fasthttpc-0.6.0/fasthttpc/cookies.py +186 -0
  14. fasthttpc-0.6.0/fasthttpc/crypto_math.py +202 -0
  15. fasthttpc-0.6.0/fasthttpc/fingerprint.py +768 -0
  16. fasthttpc-0.6.0/fasthttpc/http3/__init__.py +18 -0
  17. fasthttpc-0.6.0/fasthttpc/http3/altsvc.py +115 -0
  18. fasthttpc-0.6.0/fasthttpc/http3/async_client.py +234 -0
  19. fasthttpc-0.6.0/fasthttpc/http3/core.py +276 -0
  20. fasthttpc-0.6.0/fasthttpc/http3/fingerprint.py +95 -0
  21. fasthttpc-0.6.0/fasthttpc/http3/manager.py +199 -0
  22. fasthttpc-0.6.0/fasthttpc/http3/options.py +37 -0
  23. fasthttpc-0.6.0/fasthttpc/http3/sync_client.py +174 -0
  24. fasthttpc-0.6.0/fasthttpc/http3/verify.py +21 -0
  25. fasthttpc-0.6.0/fasthttpc/metrics.py +108 -0
  26. fasthttpc-0.6.0/fasthttpc/models/__init__.py +0 -0
  27. fasthttpc-0.6.0/fasthttpc/models/headers.py +109 -0
  28. fasthttpc-0.6.0/fasthttpc/models/request.py +100 -0
  29. fasthttpc-0.6.0/fasthttpc/models/response.py +558 -0
  30. fasthttpc-0.6.0/fasthttpc/models/urls.py +104 -0
  31. fasthttpc-0.6.0/fasthttpc/multipart.py +119 -0
  32. fasthttpc-0.6.0/fasthttpc/plugins.py +146 -0
  33. fasthttpc-0.6.0/fasthttpc/protocol/__init__.py +0 -0
  34. fasthttpc-0.6.0/fasthttpc/protocol/async_h2.py +774 -0
  35. fasthttpc-0.6.0/fasthttpc/protocol/dns_over_https.py +202 -0
  36. fasthttpc-0.6.0/fasthttpc/protocol/http1_parser.py +190 -0
  37. fasthttpc-0.6.0/fasthttpc/protocol/http2_parser.py +1753 -0
  38. fasthttpc-0.6.0/fasthttpc/py.typed +0 -0
  39. fasthttpc-0.6.0/fasthttpc/retry.py +156 -0
  40. fasthttpc-0.6.0/fasthttpc/security/__init__.py +0 -0
  41. fasthttpc-0.6.0/fasthttpc/security/alerts.py +39 -0
  42. fasthttpc-0.6.0/fasthttpc/security/cert_validator.py +441 -0
  43. fasthttpc-0.6.0/fasthttpc/security/client_cert.py +344 -0
  44. fasthttpc-0.6.0/fasthttpc/security/keyshare.py +265 -0
  45. fasthttpc-0.6.0/fasthttpc/security/mtls.py +282 -0
  46. fasthttpc-0.6.0/fasthttpc/security/session_tickets.py +466 -0
  47. fasthttpc-0.6.0/fasthttpc/security/tls12.py +1435 -0
  48. fasthttpc-0.6.0/fasthttpc/security/tls12_legacy.py +299 -0
  49. fasthttpc-0.6.0/fasthttpc/security/tls_adapter.py +1111 -0
  50. fasthttpc-0.6.0/fasthttpc/session.py +1372 -0
  51. fasthttpc-0.6.0/fasthttpc/streaming.py +218 -0
  52. fasthttpc-0.6.0/fasthttpc/timeout.py +9 -0
  53. fasthttpc-0.6.0/fasthttpc/tls13/__init__.py +26 -0
  54. fasthttpc-0.6.0/fasthttpc/tls13/_compat.py +216 -0
  55. fasthttpc-0.6.0/fasthttpc/tls13/_records.py +35 -0
  56. fasthttpc-0.6.0/fasthttpc/tls13/async_stream.py +173 -0
  57. fasthttpc-0.6.0/fasthttpc/tls13/connection.py +833 -0
  58. fasthttpc-0.6.0/fasthttpc/tls13/errors.py +22 -0
  59. fasthttpc-0.6.0/fasthttpc/tls13/events.py +57 -0
  60. fasthttpc-0.6.0/fasthttpc/tls13/sync_socket.py +102 -0
  61. fasthttpc-0.6.0/fasthttpc/tls_crafter.py +523 -0
  62. fasthttpc-0.6.0/fasthttpc/tls_tools.py +623 -0
  63. fasthttpc-0.6.0/fasthttpc/transport/__init__.py +0 -0
  64. fasthttpc-0.6.0/fasthttpc/transport/connection_pool.py +366 -0
  65. fasthttpc-0.6.0/fasthttpc/transport/happy_eyeballs.py +144 -0
  66. fasthttpc-0.6.0/fasthttpc/transport/lingering.py +50 -0
  67. fasthttpc-0.6.0/fasthttpc/transport/mock.py +83 -0
  68. fasthttpc-0.6.0/fasthttpc/transport/proxy.py +410 -0
  69. fasthttpc-0.6.0/fasthttpc.egg-info/PKG-INFO +232 -0
  70. fasthttpc-0.6.0/fasthttpc.egg-info/SOURCES.txt +133 -0
  71. fasthttpc-0.6.0/fasthttpc.egg-info/dependency_links.txt +1 -0
  72. fasthttpc-0.6.0/fasthttpc.egg-info/requires.txt +42 -0
  73. fasthttpc-0.6.0/fasthttpc.egg-info/top_level.txt +1 -0
  74. fasthttpc-0.6.0/pyproject.toml +103 -0
  75. fasthttpc-0.6.0/setup.cfg +4 -0
  76. fasthttpc-0.6.0/tests/test_api_matrix.py +151 -0
  77. fasthttpc-0.6.0/tests/test_async_api_parity.py +195 -0
  78. fasthttpc-0.6.0/tests/test_async_h2.py +923 -0
  79. fasthttpc-0.6.0/tests/test_async_parity.py +331 -0
  80. fasthttpc-0.6.0/tests/test_async_pool.py +459 -0
  81. fasthttpc-0.6.0/tests/test_async_ws.py +279 -0
  82. fasthttpc-0.6.0/tests/test_auth.py +423 -0
  83. fasthttpc-0.6.0/tests/test_backend_trio.py +706 -0
  84. fasthttpc-0.6.0/tests/test_certificate_verify.py +175 -0
  85. fasthttpc-0.6.0/tests/test_compat_versions.py +106 -0
  86. fasthttpc-0.6.0/tests/test_config.py +165 -0
  87. fasthttpc-0.6.0/tests/test_cookies.py +98 -0
  88. fasthttpc-0.6.0/tests/test_duzelt_regresyon.py +67 -0
  89. fasthttpc-0.6.0/tests/test_elapsed_clock.py +47 -0
  90. fasthttpc-0.6.0/tests/test_error_handling.py +84 -0
  91. fasthttpc-0.6.0/tests/test_fingerprint.py +143 -0
  92. fasthttpc-0.6.0/tests/test_handshake.py +257 -0
  93. fasthttpc-0.6.0/tests/test_happy_eyeballs.py +220 -0
  94. fasthttpc-0.6.0/tests/test_hooks_plugins.py +243 -0
  95. fasthttpc-0.6.0/tests/test_hpack.py +190 -0
  96. fasthttpc-0.6.0/tests/test_hrr_keyshare.py +238 -0
  97. fasthttpc-0.6.0/tests/test_http2.py +333 -0
  98. fasthttpc-0.6.0/tests/test_http3.py +412 -0
  99. fasthttpc-0.6.0/tests/test_interop_faults.py +191 -0
  100. fasthttpc-0.6.0/tests/test_interop_openssl.py +481 -0
  101. fasthttpc-0.6.0/tests/test_interop_tls12.py +116 -0
  102. fasthttpc-0.6.0/tests/test_interop_tlslite.py +145 -0
  103. fasthttpc-0.6.0/tests/test_interop_windows_yardimcilari.py +38 -0
  104. fasthttpc-0.6.0/tests/test_key_schedule.py +139 -0
  105. fasthttpc-0.6.0/tests/test_legacy_tls.py +503 -0
  106. fasthttpc-0.6.0/tests/test_mock_transport.py +160 -0
  107. fasthttpc-0.6.0/tests/test_models.py +90 -0
  108. fasthttpc-0.6.0/tests/test_mtls_fake.py +490 -0
  109. fasthttpc-0.6.0/tests/test_mtls_interop.py +207 -0
  110. fasthttpc-0.6.0/tests/test_mtls_stdlib_server.py +161 -0
  111. fasthttpc-0.6.0/tests/test_mtls_unit.py +403 -0
  112. fasthttpc-0.6.0/tests/test_parmakizi_profilleri.py +431 -0
  113. fasthttpc-0.6.0/tests/test_profile_headers.py +261 -0
  114. fasthttpc-0.6.0/tests/test_proxy.py +334 -0
  115. fasthttpc-0.6.0/tests/test_psk_resumption_async.py +339 -0
  116. fasthttpc-0.6.0/tests/test_psk_resumption_local.py +180 -0
  117. fasthttpc-0.6.0/tests/test_record_layer_perf.py +138 -0
  118. fasthttpc-0.6.0/tests/test_redirects.py +32 -0
  119. fasthttpc-0.6.0/tests/test_request_compat.py +226 -0
  120. fasthttpc-0.6.0/tests/test_response_compat.py +76 -0
  121. fasthttpc-0.6.0/tests/test_retry.py +170 -0
  122. fasthttpc-0.6.0/tests/test_saha_regresyon.py +207 -0
  123. fasthttpc-0.6.0/tests/test_session_tickets.py +142 -0
  124. fasthttpc-0.6.0/tests/test_streaming.py +182 -0
  125. fasthttpc-0.6.0/tests/test_streaming_async.py +123 -0
  126. fasthttpc-0.6.0/tests/test_streaming_h2.py +244 -0
  127. fasthttpc-0.6.0/tests/test_streaming_response.py +141 -0
  128. fasthttpc-0.6.0/tests/test_tls12.py +812 -0
  129. fasthttpc-0.6.0/tests/test_tls12_linger.py +107 -0
  130. fasthttpc-0.6.0/tests/test_tls13_core.py +359 -0
  131. fasthttpc-0.6.0/tests/test_tls13_wrappers.py +207 -0
  132. fasthttpc-0.6.0/tests/test_tls_record.py +186 -0
  133. fasthttpc-0.6.0/tests/test_trust_store_cache.py +154 -0
  134. fasthttpc-0.6.0/tests/test_verify_ca_path.py +98 -0
  135. fasthttpc-0.6.0/tests/test_websocket_handshake.py +148 -0
@@ -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.
@@ -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
+ [![CI](https://github.com/bu-ra34/fasthttpc/actions/workflows/ci.yml/badge.svg)](https://github.com/bu-ra34/fasthttpc/actions/workflows/ci.yml)
70
+ [![PyPI](https://img.shields.io/pypi/v/fasthttpc.svg)](https://pypi.org/project/fasthttpc/)
71
+ [![Python versions](https://img.shields.io/pypi/pyversions/fasthttpc.svg)](https://pypi.org/project/fasthttpc/)
72
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
73
+ [![Docs](https://img.shields.io/badge/docs-mkdocs-informational.svg)](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
+ [![CI](https://github.com/bu-ra34/fasthttpc/actions/workflows/ci.yml/badge.svg)](https://github.com/bu-ra34/fasthttpc/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/fasthttpc.svg)](https://pypi.org/project/fasthttpc/)
5
+ [![Python versions](https://img.shields.io/pypi/pyversions/fasthttpc.svg)](https://pypi.org/project/fasthttpc/)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
+ [![Docs](https://img.shields.io/badge/docs-mkdocs-informational.svg)](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
+ ]