Skip to content

Commit e0677a1

Browse files
committed
Update README.md
1 parent ce0a87b commit e0677a1

File tree

1 file changed

+146
-140
lines changed

1 file changed

+146
-140
lines changed

README.md

Lines changed: 146 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -1,195 +1,201 @@
11
# Python-TLS-Client-Async
22

33
[![PyPI version](https://img.shields.io/pypi/v/async_tls_client.svg)](https://pypi.org/project/async_tls_client/)
4+
[![Python versions](https://img.shields.io/pypi/pyversions/async_tls_client.svg)](https://pypi.org/project/async_tls_client/)
5+
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
46

5-
> Asyncio fork of [Florian Zager's Python-TLS-Client](https://github.com/FlorianREGAZ/Python-Tls-Client)
6-
> with updated dependencies and modern Python support.
7+
Asyncio-first TLS client for Python with advanced fingerprinting capabilities. Modern fork of [Python-TLS-Client](https://github.com/FlorianREGAZ/Python-Tls-Client) with enhanced features and active maintenance.
78

8-
Python-TLS-Client-Async is a fork of [Python-TLS-Client](https://github.com/FlorianREGAZ/Python-Tls-Client) with added
9-
support for asyncio. This library allows you to perform advanced HTTP requests while maintaining compatibility with
10-
asynchronous programming patterns in Python.
11-
12-
The fork was created due to the lack of updates in the original repository, while the underlying GoLang
13-
library [tls-client](https://github.com/bogdanfinn/tls-client) continues to evolve actively. This project aims to keep
14-
up with the latest developments in the GoLang library and provide a modern, asynchronous interface for Python users.
9+
```python
10+
from async_tls_client import AsyncClient
11+
import asyncio
1512

16-
# Installation
13+
async def main():
14+
async with AsyncClient(
15+
client_identifier="chrome120",
16+
random_tls_extension_order=True
17+
) as client:
18+
response = await client.get("https://tls.peet.ws/api/all")
19+
print(f"Detected TLS fingerprint: {response.json()['tls']['ja3_hash']}")
1720

18-
```bash
19-
pip install async_tls_client
21+
asyncio.run(main())
2022
```
2123

22-
# Features
23-
24-
- Asyncio-based API for making HTTP requests.
25-
- Inspired by the syntax of [requests](https://github.com/psf/requests), making it familiar and easy to use.
26-
- Supports advanced TLS configurations like JA3, HTTP/2 settings, and more.
27-
28-
# Asynchronous Design
24+
## Features ✨
2925

30-
The project achieves asynchronicity by leveraging Python's `asyncio` framework. Here’s how it works:
26+
- **Full Async Support**: Built with asyncio for high-performance concurrent requests
27+
- **Modern TLS Fingerprinting**: JA3, JA4, HTTP/2 fingerprints and TLS 1.3 support
28+
- **Client Profiles**: 50+ preconfigured clients (Chrome, Firefox, Safari, iOS, Android)
29+
- **Advanced Configuration**:
30+
- Custom TLS cipher suites & extensions
31+
- HTTP/2 and QUIC protocol support
32+
- Certificate pinning and compression
33+
- Proxy support (HTTP/S, SOCKS4/5)
34+
- **Auto-Cookie Management**: Session persistence with configurable cookie jars
35+
- **Request Manipulation**: Header ordering, pseudo-header customization, and priority control
3136

32-
1. **Thread Offloading for Blocking Operations:**
33-
Since the underlying `tls-client` library is implemented in Go and provides a blocking API, the project uses
34-
`asyncio.to_thread` to offload these blocking operations to separate threads. This allows the Python event loop to
35-
remain non-blocking while interacting with the synchronous Go library.
37+
## Why This Fork? 🚀
3638

37-
2. **Custom Async Session Class:**
38-
The `AsyncSession` class wraps synchronous operations in asynchronous methods. For example, requests are executed in
39-
threads to ensure compatibility with asyncio, while responses are processed asynchronously.
39+
This project was created to address the lack of updates in the original Python-TLS-Client while incorporating:
40+
- Modern Python 3.9+ features and async/await syntax
41+
- Active updates from the underlying [tls-client](https://github.com/bogdanfinn/tls-client) Go library
42+
- Improved error handling and debugging capabilities
43+
- Better documentation and developer experience
44+
- Enhanced security features for enterprise use cases
4045

41-
3. **Async Context Management:**
42-
The session supports asynchronous context management using `async with`, ensuring proper cleanup of resources like
43-
sessions and memory allocations when the session is closed.
46+
## Installation 📦
4447

45-
4. **Seamless Integration with Asyncio:**
46-
By providing async versions of common HTTP methods (`get`, `post`, `put`, etc.), the library integrates smoothly into
47-
existing asyncio-based workflows.
48-
49-
# Examples
48+
```bash
49+
pip install async_tls_client
50+
```
5051

51-
The syntax is similar to the original Python-TLS-Client library but adapted for asynchronous workflows.
52+
## Quickstart 🚀
5253

53-
## Example 1 - Preset
54+
### Basic Usage
5455

5556
```python
56-
import async_tls_client
57+
from async_tls_client import AsyncClient
5758
import asyncio
5859

59-
60-
# Example of client identifiers:
61-
# Chrome --> chrome_103, chrome_104, chrome_105, chrome_106, chrome_107, chrome_108, chrome109, chrome110,
62-
# chrome111, chrome112, chrome_116_PSK, chrome_116_PSK_PQ, chrome_117, chrome_120
63-
# Firefox --> firefox_102, firefox_104, firefox108, Firefox110, firefox_117, firefox_120
64-
# Opera --> opera_89, opera_90
65-
# Safari --> safari_15_3, safari_15_6_1, safari_16_0
66-
# iOS --> safari_ios_15_5, safari_ios_15_6, safari_ios_16_0
67-
# iPadOS --> safari_ios_15_6
68-
# Android --> okhttp4_android_7, okhttp4_android_8, okhttp4_android_9, okhttp4_android_10, okhttp4_android_11,
69-
# okhttp4_android_12, okhttp4_android_13
70-
7160
async def main():
72-
session = async_tls_client.AsyncSession(
73-
client_identifier="chrome112",
74-
random_tls_extension_order=True
75-
)
76-
77-
response = await session.get(
78-
"https://www.example.com/",
79-
headers={"key1": "value1"},
80-
proxy="http://user:password@host:port"
81-
)
82-
83-
print(response.text)
84-
await session.close()
85-
61+
async with AsyncClient("chrome120") as client:
62+
response = await client.get(
63+
"https://httpbin.org/json",
64+
headers={"X-API-Key": "secret"},
65+
proxy="http://user:pass@proxy:port"
66+
)
67+
print(f"Status: {response.status_code}")
68+
print(f"Headers: {response.headers}")
69+
print(f"JSON: {response.json()}")
8670

8771
asyncio.run(main())
8872
```
8973

90-
## Example 2 - Custom
74+
### Advanced Configuration
9175

9276
```python
93-
import async_tls_client
94-
import asyncio
77+
from async_tls_client import AsyncClient
78+
79+
client = AsyncClient(
80+
ja3_string="771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0",
81+
h2_settings={
82+
"HEADER_TABLE_SIZE": 65536,
83+
"MAX_CONCURRENT_STREAMS": 1000,
84+
"INITIAL_WINDOW_SIZE": 6291456,
85+
"MAX_HEADER_LIST_SIZE": 262144
86+
},
87+
supported_signature_algorithms=[
88+
"ECDSAWithP256AndSHA256",
89+
"PSSWithSHA256",
90+
"PKCS1WithSHA256",
91+
"ECDSAWithP384AndSHA384",
92+
"PSSWithSHA384",
93+
"PKCS1WithSHA512",
94+
],
95+
certificate_pinning={
96+
"example.com": [
97+
"sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
98+
]
99+
}
100+
)
101+
```
95102

103+
## Client Profiles 🕶️
96104

97-
async def main():
98-
session = async_tls_client.AsyncSession(
99-
ja3_string="771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0",
100-
h2_settings={
101-
"HEADER_TABLE_SIZE": 65536,
102-
"MAX_CONCURRENT_STREAMS": 1000,
103-
"INITIAL_WINDOW_SIZE": 6291456,
104-
"MAX_HEADER_LIST_SIZE": 262144
105-
},
106-
h2_settings_order=[
107-
"HEADER_TABLE_SIZE",
108-
"MAX_CONCURRENT_STREAMS",
109-
"INITIAL_WINDOW_SIZE",
110-
"MAX_HEADER_LIST_SIZE"
111-
],
112-
supported_signature_algorithms=[
113-
"ECDSAWithP256AndSHA256",
114-
"PSSWithSHA256",
115-
"PKCS1WithSHA256",
116-
"ECDSAWithP384AndSHA384",
117-
"PSSWithSHA384",
118-
"PKCS1WithSHA384",
119-
"PSSWithSHA512",
120-
"PKCS1WithSHA512",
121-
],
122-
supported_versions=["GREASE", "1.3", "1.2"],
123-
key_share_curves=["GREASE", "X25519"],
124-
cert_compression_algo="brotli",
125-
pseudo_header_order=[
126-
":method",
127-
":authority",
128-
":scheme",
129-
":path"
130-
],
131-
connection_flow=15663105,
132-
header_order=[
133-
"accept",
134-
"user-agent",
135-
"accept-encoding",
136-
"accept-language"
137-
]
138-
)
105+
Preconfigured client identifiers (https://github.com/bogdanfinn/tls-client/blob/master/profiles/profiles.go):
139106

140-
response = await session.post(
141-
"https://www.example.com/",
142-
headers={"key1": "value1"},
143-
json={"key1": "key2"}
144-
)
107+
| Browser/Framework | Available Profiles |
108+
|-------------------------|------------------------------------------------------------------------------------|
109+
| Chrome | chrome_103 - chrome_133 (including PSK variants: 116_PSK, 116_PSK_PQ, 131_PSK, 133_PSK) |
110+
| Firefox | firefox_102 - firefox_135 |
111+
| Safari (Desktop) | safari_15_6_1, safari_16_0, safari_ipad_15_6 |
112+
| Safari (iOS) | safari_ios_15_5 - safari_ios_18_0 |
113+
| Opera | opera_89 - opera_91 |
114+
| Android (OkHttp) | okhttp4_android_7 - okhttp4_android_13 |
115+
| iOS (Custom) | mms_ios (v1, v2, v3), mesh_ios (v1, v2), confirmed_ios, zalando_ios_mobile, nike_ios_mobile |
116+
| Android (Custom) | mesh_android (v1, v2), confirmed_android, zalando_android_mobile, nike_android_mobile |
117+
| Cloudflare | cloudscraper |
145118

146-
print(response.text)
147-
await session.close()
119+
## Advanced Features 🔧
148120

121+
### Custom Fingerprint Configuration
149122

150-
asyncio.run(main())
123+
```python
124+
client = AsyncClient(
125+
ja3_string="771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0",
126+
h2_settings_order=["HEADER_TABLE_SIZE", "MAX_CONCURRENT_STREAMS"],
127+
pseudo_header_order=[":method", ":authority", ":scheme", ":path"],
128+
header_order=["accept", "user-agent", "accept-encoding"],
129+
force_http1=False,
130+
cert_compression_algo="brotli"
131+
)
151132
```
152133

153-
# PyInstaller / PyArmor
134+
### Certificate Pinning
154135

155-
If you want to package the library with PyInstaller or PyArmor, make sure to include the necessary dependencies:
136+
```python
137+
client = AsyncClient(
138+
certificate_pinning={
139+
"api.bank.com": [
140+
"sha256/7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=",
141+
"sha256/YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg="
142+
]
143+
}
144+
)
145+
```
156146

157-
## Linux - Ubuntu / x86
147+
### Proxy Support
158148

159-
```bash
160-
--add-binary '{path_to_library}/async_tls_client/dependencies/tls-client-x86.so:async_tls_client/dependencies'
149+
```python
150+
response = await client.get(
151+
"https://api.example.com",
152+
proxy="socks5://user:pass@proxy:1080"
153+
)
161154
```
162155

163-
## Linux Alpine / AMD64
156+
## Asynchronous Design 🚧
164157

165-
```bash
166-
--add-binary '{path_to_library}/async_tls_client/dependencies/tls-client-amd64.so:async_tls_client/dependencies'
167-
```
158+
The client leverages Python's asyncio through three key strategies:
168159

169-
## MacOS M1 and older
160+
1. **Non-blocking I/O**
161+
- Network operations run in separate threads using `asyncio.to_thread`
162+
- Go TLS client handles remain managed in background executors
170163

171-
```bash
172-
--add-binary '{path_to_library}/async_tls_client/dependencies/tls-client-x86.dylib:async_tls_client/dependencies'
173-
```
164+
2. **Session Management**
165+
- `AsyncClient` context manager handles automatic cleanup
166+
- Connection pooling with automatic keep-alives
167+
- Cookie persistence across requests
168+
169+
3. **Resource Optimization**
170+
- Zero-copy body handling for large responses
171+
- Lazy initialization of heavy resources
172+
- Automatic memory cleanup of Go pointers
173+
174+
## Packaging 📦
174175

175-
## MacOS M2
176+
When using PyInstaller/PyArmor, include the shared library:
176177

178+
### Windows
177179
```bash
178-
--add-binary '{path_to_library}/async_tls_client/dependencies/tls-client-arm64.dylib:async_tls_client/dependencies'
180+
--add-binary 'async_tls_client/dependencies/tls-client-64.dll;async_tls_client/dependencies'
179181
```
180182

181-
## Windows
183+
### Linux
184+
```bash
185+
--add-binary 'async_tls_client/dependencies/tls-client-x86.so:async_tls_client/dependencies'
186+
```
182187

188+
### macOS
183189
```bash
184-
--add-binary '{path_to_library}/async_tls_client/dependencies/tls-client-64.dll;async_tls_client/dependencies'
190+
--add-binary 'async_tls_client/dependencies/tls-client-arm64.dylib:async_tls_client/dependencies'
185191
```
186192

187-
# Acknowledgements
193+
## Acknowledgements 🙏
188194

189-
This project is a fork of [Python-TLS-Client](https://github.com/FlorianREGAZ/Python-Tls-Client), with significant
190-
contributions to support asyncio. The original library is based
191-
on [tls-client](https://github.com/bogdanfinn/tls-client) by [Bogdanfinn](https://github.com/bogdanfinn).
195+
- Original Python implementation: [FlorianREGAZ/Python-Tls-Client](https://github.com/FlorianREGAZ/Python-Tls-Client)
196+
- Core TLS implementation: [bogdanfinn/tls-client](https://github.com/bogdanfinn/tls-client)
197+
- Inspiration: [psf/requests](https://github.com/psf/requests)
192198

193-
The syntax aims to remain close to [requests](https://github.com/psf/requests) to ensure ease of use and familiarity for
194-
Python developers.
199+
## License 📄
195200

201+
MIT License - See [LICENSE](LICENSE) for details

0 commit comments

Comments
 (0)