Skip to content

Commit 4b865bc

Browse files
committed
Update README.md
1 parent 66257e4 commit 4b865bc

File tree

2 files changed

+154
-98
lines changed

2 files changed

+154
-98
lines changed

README.md

Lines changed: 153 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,55 @@
1-
# Python-TLS-Client
2-
Python-TLS-Client is an advanced HTTP library based on requests and tls-client.
1+
# Python-TLS-Client-Async
2+
3+
Python-TLS-Client-Async is a fork of [Python-TLS-Client](https://github.com/FlorianREGAZ/Python-Tls-Client) with added
4+
support for asyncio. This library allows you to perform advanced HTTP requests while maintaining compatibility with
5+
asynchronous programming patterns in Python.
36

47
# Installation
8+
9+
```bash
10+
pip install async_tls_client
511
```
6-
pip install tls-client
7-
```
12+
13+
# Features
14+
15+
- Asyncio-based API for making HTTP requests.
16+
- Inspired by the syntax of [requests](https://github.com/psf/requests), making it familiar and easy to use.
17+
- Supports advanced TLS configurations like JA3, HTTP/2 settings, and more.
18+
19+
# Asynchronous Design
20+
21+
The project achieves asynchronicity by leveraging Python's `asyncio` framework. Here’s how it works:
22+
23+
1. **Thread Offloading for Blocking Operations:**
24+
Since the underlying `tls-client` library is implemented in Go and provides a blocking API, the project uses
25+
`asyncio.to_thread` to offload these blocking operations to separate threads. This allows the Python event loop to
26+
remain non-blocking while interacting with the synchronous Go library.
27+
28+
2. **Custom Async Session Class:**
29+
The `AsyncSession` class wraps synchronous operations in asynchronous methods. For example, requests are executed in
30+
threads to ensure compatibility with asyncio, while responses are processed asynchronously.
31+
32+
3. **Async Context Management:**
33+
The session supports asynchronous context management using `async with`, ensuring proper cleanup of resources like
34+
sessions and memory allocations when the session is closed.
35+
36+
4. **Seamless Integration with Asyncio:**
37+
By providing async versions of common HTTP methods (`get`, `post`, `put`, etc.), the library integrates smoothly into
38+
existing asyncio-based workflows.
839

940
# Examples
10-
The syntax is inspired by [requests](https://github.com/psf/requests), so its very similar and there are only very few things that are different.
1141

12-
Example 1 - Preset:
42+
The syntax is similar to the original Python-TLS-Client library but adapted for asynchronous workflows.
43+
44+
## Example 1 - Preset
45+
1346
```python
14-
import tls_client
47+
import async_tls_client
48+
import asyncio
1549

16-
# You can also use the following as `client_identifier`:
17-
# Chrome --> chrome_103, chrome_104, chrome_105, chrome_106, chrome_107, chrome_108, chrome109, Chrome110,
50+
51+
# Example of client identifiers:
52+
# Chrome --> chrome_103, chrome_104, chrome_105, chrome_106, chrome_107, chrome_108, chrome109, chrome110,
1853
# chrome111, chrome112, chrome_116_PSK, chrome_116_PSK_PQ, chrome_117, chrome_120
1954
# Firefox --> firefox_102, firefox_104, firefox108, Firefox110, firefox_117, firefox_120
2055
# Opera --> opera_89, opera_90
@@ -23,108 +58,129 @@ import tls_client
2358
# iPadOS --> safari_ios_15_6
2459
# Android --> okhttp4_android_7, okhttp4_android_8, okhttp4_android_9, okhttp4_android_10, okhttp4_android_11,
2560
# okhttp4_android_12, okhttp4_android_13
26-
#
27-
# more client identifiers can be found in settings.py
28-
29-
session = tls_client.Session(
30-
client_identifier="chrome112",
31-
random_tls_extension_order=True
32-
)
33-
34-
res = session.get(
35-
"https://www.example.com/",
36-
headers={
37-
"key1": "value1",
38-
},
39-
proxy="http://user:password@host:port"
40-
)
61+
62+
async def main():
63+
session = async_tls_client.AsyncSession(
64+
client_identifier="chrome112",
65+
random_tls_extension_order=True
66+
)
67+
68+
response = await session.get(
69+
"https://www.example.com/",
70+
headers={"key1": "value1"},
71+
proxy="http://user:password@host:port"
72+
)
73+
74+
print(response.text)
75+
await session.close()
76+
77+
78+
asyncio.run(main())
4179
```
4280

43-
Example 2 - Custom:
81+
## Example 2 - Custom
82+
4483
```python
45-
import tls_client
46-
47-
session = tls_client.Session(
48-
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",
49-
h2_settings={
50-
"HEADER_TABLE_SIZE": 65536,
51-
"MAX_CONCURRENT_STREAMS": 1000,
52-
"INITIAL_WINDOW_SIZE": 6291456,
53-
"MAX_HEADER_LIST_SIZE": 262144
54-
},
55-
h2_settings_order=[
56-
"HEADER_TABLE_SIZE",
57-
"MAX_CONCURRENT_STREAMS",
58-
"INITIAL_WINDOW_SIZE",
59-
"MAX_HEADER_LIST_SIZE"
60-
],
61-
supported_signature_algorithms=[
62-
"ECDSAWithP256AndSHA256",
63-
"PSSWithSHA256",
64-
"PKCS1WithSHA256",
65-
"ECDSAWithP384AndSHA384",
66-
"PSSWithSHA384",
67-
"PKCS1WithSHA384",
68-
"PSSWithSHA512",
69-
"PKCS1WithSHA512",
70-
],
71-
supported_versions=["GREASE", "1.3", "1.2"],
72-
key_share_curves=["GREASE", "X25519"],
73-
cert_compression_algo="brotli",
74-
pseudo_header_order=[
75-
":method",
76-
":authority",
77-
":scheme",
78-
":path"
79-
],
80-
connection_flow=15663105,
81-
header_order=[
82-
"accept",
83-
"user-agent",
84-
"accept-encoding",
85-
"accept-language"
86-
]
87-
)
88-
89-
res = session.post(
90-
"https://www.example.com/",
91-
headers={
92-
"key1": "value1",
93-
},
94-
json={
95-
"key1": "key2"
96-
}
97-
)
84+
import async_tls_client
85+
import asyncio
86+
87+
88+
async def main():
89+
session = async_tls_client.AsyncSession(
90+
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",
91+
h2_settings={
92+
"HEADER_TABLE_SIZE": 65536,
93+
"MAX_CONCURRENT_STREAMS": 1000,
94+
"INITIAL_WINDOW_SIZE": 6291456,
95+
"MAX_HEADER_LIST_SIZE": 262144
96+
},
97+
h2_settings_order=[
98+
"HEADER_TABLE_SIZE",
99+
"MAX_CONCURRENT_STREAMS",
100+
"INITIAL_WINDOW_SIZE",
101+
"MAX_HEADER_LIST_SIZE"
102+
],
103+
supported_signature_algorithms=[
104+
"ECDSAWithP256AndSHA256",
105+
"PSSWithSHA256",
106+
"PKCS1WithSHA256",
107+
"ECDSAWithP384AndSHA384",
108+
"PSSWithSHA384",
109+
"PKCS1WithSHA384",
110+
"PSSWithSHA512",
111+
"PKCS1WithSHA512",
112+
],
113+
supported_versions=["GREASE", "1.3", "1.2"],
114+
key_share_curves=["GREASE", "X25519"],
115+
cert_compression_algo="brotli",
116+
pseudo_header_order=[
117+
":method",
118+
":authority",
119+
":scheme",
120+
":path"
121+
],
122+
connection_flow=15663105,
123+
header_order=[
124+
"accept",
125+
"user-agent",
126+
"accept-encoding",
127+
"accept-language"
128+
]
129+
)
130+
131+
response = await session.post(
132+
"https://www.example.com/",
133+
headers={"key1": "value1"},
134+
json={"key1": "key2"}
135+
)
136+
137+
print(response.text)
138+
await session.close()
139+
140+
141+
asyncio.run(main())
98142
```
99143

100-
# Pyinstaller / Pyarmor
101-
**If you want to pack the library with Pyinstaller or Pyarmor, make sure to add this to your command:**
144+
# PyInstaller / PyArmor
102145

103-
Linux - Ubuntu / x86:
104-
```
105-
--add-binary '{path_to_library}/tls_client/dependencies/tls-client-x86.so:tls_client/dependencies'
106-
```
146+
If you want to package the library with PyInstaller or PyArmor, make sure to include the necessary dependencies:
107147

108-
Linux Alpine / AMD64:
109-
```
110-
--add-binary '{path_to_library}/tls_client/dependencies/tls-client-amd64.so:tls_client/dependencies'
111-
```
148+
## Linux - Ubuntu / x86
112149

113-
MacOS M1 and older:
114-
```
115-
--add-binary '{path_to_library}/tls_client/dependencies/tls-client-x86.dylib:tls_client/dependencies'
150+
```bash
151+
--add-binary '{path_to_library}/async_tls_client/dependencies/tls-client-x86.so:async_tls_client/dependencies'
116152
```
117153

118-
MacOS M2:
154+
## Linux Alpine / AMD64
155+
156+
```bash
157+
--add-binary '{path_to_library}/async_tls_client/dependencies/tls-client-amd64.so:async_tls_client/dependencies'
119158
```
120-
--add-binary '{path_to_library}/tls_client/dependencies/tls-client-arm64.dylib:tls_client/dependencies'
159+
160+
## MacOS M1 and older
161+
162+
```bash
163+
--add-binary '{path_to_library}/async_tls_client/dependencies/tls-client-x86.dylib:async_tls_client/dependencies'
121164
```
122165

123-
Windows:
166+
## MacOS M2
167+
168+
```bash
169+
--add-binary '{path_to_library}/async_tls_client/dependencies/tls-client-arm64.dylib:async_tls_client/dependencies'
124170
```
125-
--add-binary '{path_to_library}/tls_client/dependencies/tls-client-64.dll;tls_client/dependencies'
171+
172+
## Windows
173+
174+
```bash
175+
--add-binary '{path_to_library}/async_tls_client/dependencies/tls-client-64.dll;async_tls_client/dependencies'
126176
```
127177

128178
# Acknowledgements
129-
Big shout out to [Bogdanfinn](https://github.com/bogdanfinn) for open sourcing his [tls-client](https://github.com/bogdanfinn/tls-client) in Golang.
130-
Also I wanted to keep the syntax as similar as possible to [requests](https://github.com/psf/requests), as most people use it and are familiar with it!
179+
180+
This project is a fork of [Python-TLS-Client](https://github.com/FlorianREGAZ/Python-Tls-Client), with significant
181+
contributions to support asyncio. The original library is based
182+
on [tls-client](https://github.com/bogdanfinn/tls-client) by [Bogdanfinn](https://github.com/bogdanfinn).
183+
184+
The syntax aims to remain close to [requests](https://github.com/psf/requests) to ensure ease of use and familiarity for
185+
Python developers.
186+

async_tls_client/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66

77
__title__ = "async_tls_client"
88
__description__ = "Fork of tls-client with asyncio."
9-
__version__ = "1.0.3"
9+
__version__ = "1.0.4"
1010
__author__ = "Diprog"
1111
__license__ = "MIT"

0 commit comments

Comments
 (0)