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+
0 commit comments