Skip to content

Commit 4da8f3f

Browse files
feat: rotator supported
1 parent 7964828 commit 4da8f3f

File tree

13 files changed

+1419
-174
lines changed

13 files changed

+1419
-174
lines changed

.pre-commit-config.yaml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
exclude: '^docs.sh/|scripts/'
22
default_stages: [pre-commit]
33

4-
default_language_version:
5-
python: python3.10
6-
74
repos:
85
- repo: https://github.com/pre-commit/pre-commit-hooks
9-
rev: v4.5.0
6+
rev: v6.0.0
107
hooks:
118
- id: trailing-whitespace
129
- id: end-of-file-fixer
@@ -22,12 +19,12 @@ repos:
2219

2320
# run the isort.
2421
- repo: https://github.com/PyCQA/isort
25-
rev: 5.13.2
22+
rev: 6.1.0
2623
hooks:
2724
- id: isort
2825

2926
# run the flake8.
3027
- repo: https://github.com/PyCQA/flake8
31-
rev: 7.0.0
28+
rev: 7.3.0
3229
hooks:
3330
- id: flake8

docs/advanced/rotators.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Using Rotators
2+
3+
The `tls_requests` library is designed to be smart out of the box. By default, it automatically rotates through realistic headers and client identifiers to make your requests appear authentic and avoid detection.
4+
5+
This guide explains how these default rotators work and how you can customize or disable them.
6+
7+
* * *
8+
9+
### Header Rotator
10+
11+
**Default Behavior: Automatic Rotation**
12+
13+
When you initialize a `Client` without specifying the `headers` parameter, it will **automatically rotate** through a built-in collection of header templates that mimic popular browsers like Chrome, Firefox, and Safari across different operating systems.
14+
15+
```python
16+
import tls_requests
17+
18+
# No extra configuration needed!
19+
# This client will automatically use a different, realistic header set for each request.
20+
with tls_requests.Client(headers=tls_requests.HeaderRotator()) as client:
21+
# Request 1 might have Chrome headers
22+
res1 = client.get("https://httpbin.org/headers")
23+
print(f"Request 1 UA: {res1.json()['headers']['User-Agent']}")
24+
25+
# Request 2 might have Firefox headers
26+
res2 = client.get("https://httpbin.org/headers")
27+
print(f"Request 2 UA: {res2.json()['headers']['User-Agent']}")
28+
```
29+
30+
**How to Override the Default Behavior:**
31+
32+
- **To rotate through your own list of headers**, pass a `list` of `dict`s:
33+
```python
34+
my_headers = [{"User-Agent": "MyBot/1.0"}, {"User-Agent": "MyBot/2.0"}]
35+
client = tls_requests.Client(headers=my_headers)
36+
```
37+
38+
- **To use a single, static set of headers (no rotation)**, pass a single `dict`:
39+
```python
40+
static_headers = {"User-Agent": "Always-The-Same-Bot/1.0"}
41+
client = tls_requests.Client(headers=static_headers)
42+
```
43+
44+
- **To completely disable default headers**, pass `None`:
45+
```python
46+
# This client will not add any default headers (like User-Agent).
47+
client = tls_requests.Client(headers=None)
48+
```
49+
50+
* * *
51+
52+
### TLS Client Identifier Rotator
53+
54+
**Default Behavior: Automatic Rotation**
55+
56+
Similar to headers, the `Client` **defaults to rotating** through all supported client identifier profiles (e.g., `chrome_120`, `firefox_120`, `safari_16_0`, etc.). This changes your TLS fingerprint with every request, an advanced technique to evade sophisticated anti-bot systems.
57+
58+
```python
59+
import tls_requests
60+
61+
# This client automatically changes its TLS fingerprint for each request.
62+
with tls_requests.Client(client_identifier=tls_requests.TLSIdentifierRotator()) as client:
63+
# These two requests will have different TLS profiles.
64+
res1 = client.get("https://tls.browserleaks.com/json")
65+
res2 = client.get("https://tls.browserleaks.com/json")
66+
```
67+
68+
**How to Override the Default Behavior:**
69+
70+
- **To rotate through a specific list of identifiers**, pass a `list` of strings:
71+
```python
72+
my_identifiers = ["chrome_120", "safari_16_0"]
73+
client = tls_requests.Client(client_identifier=my_identifiers)
74+
```
75+
76+
- **To use a single, static identifier**, pass a string:
77+
```python
78+
client = tls_requests.Client(client_identifier="chrome_120")
79+
```
80+
- **To disable rotation and use the library's single default identifier**, pass `None`:
81+
```python
82+
client = tls_requests.Client(client_identifier=None)
83+
```
84+
85+
* * *
86+
87+
### Proxy Rotator
88+
89+
Unlike headers and client identifiers, proxy rotation is **not enabled by default**, as the library cannot provide a list of free proxies. You must provide your own list to enable this feature.
90+
91+
To enable proxy rotation, pass a list of proxy strings to the `proxy` parameter. The library will automatically use a `weighted` strategy, prioritizing proxies that perform well.
92+
93+
```python
94+
import tls_requests
95+
96+
proxy_list = [
97+
"http://user1:pass1@proxy.example.com:8080",
98+
"http://user2:pass2@proxy.example.com:8081",
99+
"socks5://proxy.example.com:8082",
100+
"proxy.example.com:8083", # (defaults to http)
101+
"http://user:pass@proxy.example.com:8084|1.0|US", # http://user:pass@host:port|weight|region
102+
]
103+
104+
# Provide a list to enable proxy rotation.
105+
with tls_requests.Client(proxy=proxy_list) as client:
106+
response = client.get("https://httpbin.org/get")
107+
```
108+
109+
For more control, you can create a `ProxyRotator` instance with a specific strategy:
110+
111+
```python
112+
from tls_requests.models.rotators import ProxyRotator
113+
114+
rotator = ProxyRotator.from_file(proxy_list, strategy="round_robin")
115+
116+
with tls_requests.Client(proxy=rotator) as client:
117+
response = client.get("https://httpbin.org/get")
118+
```
119+
120+
> **Note:** The `Client` automatically provides performance feedback (success/failure, latency) to the `ProxyRotator`, making the `weighted` strategy highly effective.
121+
122+
* * *
123+
124+
### Asynchronous Support
125+
126+
All rotator features, including the smart defaults, work identically with `AsyncClient`.
127+
128+
```python
129+
import tls_requests
130+
import asyncio
131+
132+
async def main():
133+
# This async client automatically uses default header and identifier rotation.
134+
async with tls_requests.AsyncClient(
135+
headers=tls_requests.HeaderRotator(),
136+
client_identifier=tls_requests.TLSIdentifierRotator()
137+
) as client:
138+
tasks = [client.get("https://httpbin.org/get") for _ in range(2)]
139+
responses = await asyncio.gather(*tasks)
140+
141+
for i, r in enumerate(responses):
142+
print(f"Async Request {i+1} status: {r.status_code}")
143+
144+
asyncio.run(main())
145+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ nav:
3030
- Authentication: 'advanced/authentication.md'
3131
- Hooks: 'advanced/hooks.md'
3232
- Proxies: 'advanced/proxies.md'
33+
- Rotators: 'advanced/rotators.md'
3334
- TLS Client:
3435
- Install: 'tls/install.md'
3536
- Wrapper TLS Client: 'tls/index.md'

0 commit comments

Comments
 (0)