Skip to content

Commit 4f2ee84

Browse files
authored
Add Async Support (#124)
* Refactor: Move exceptions to a separate module * Refactor: Move exceptions to a separate module * Refactor: Move exceptions to a separate module * Add async support * Fix: Set follow_redirects=True for all AsyncClient instances * Fix: Resolve example image paths in tests
1 parent 14e8494 commit 4f2ee84

File tree

172 files changed

+4965
-900
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

172 files changed

+4965
-900
lines changed

README.md

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ from twocaptcha import TwoCaptcha
7676

7777
solver = TwoCaptcha('YOUR_API_KEY')
7878
```
79+
80+
<details>
81+
<summary>Async</summary>
82+
83+
```python
84+
from twocaptcha import AsyncTwoCaptcha
85+
86+
solver = AsyncTwoCaptcha('YOUR_API_KEY')
87+
```
88+
89+
</details>
90+
7991
Also, there are a few options that can be configured:
8092

8193
```python
@@ -517,7 +529,55 @@ proxy={
517529
```
518530

519531
## Async calls
520-
You can also make async calls with [asyncio], for example:
532+
533+
To use the async version, just replace `TwoCaptcha` with `AsyncTwoCaptcha`:
534+
535+
```python
536+
import asyncio
537+
from twocaptcha import AsyncTwoCaptcha
538+
539+
async def solve_captcha():
540+
solver = AsyncTwoCaptcha('YOUR_API_KEY')
541+
542+
try:
543+
recaptcha_result = await solver.recaptcha(...)
544+
return recaptcha_result
545+
except Exception as e:
546+
print(e)
547+
return None
548+
549+
if __name__ == '__main__':
550+
result = asyncio.run(solve_captcha())
551+
```
552+
553+
The `AsyncTwoCaptcha` class supports all the same methods and parameters as the synchronous `TwoCaptcha` class but operates asynchronously. Configuration is identical.
554+
555+
### Solving Multiple Captchas in Parallel
556+
557+
One of the main advantages of using async support is the ability to solve multiple captchas concurrently:
558+
559+
```python
560+
async def solve_multiple_captchas():
561+
solver = AsyncTwoCaptcha('YOUR_API_KEY')
562+
563+
# Start all tasks simultaneously
564+
task1 = asyncio.create_task(solver.text('What color is the sky on a clear day?'))
565+
task2 = asyncio.create_task(solver.text('What is 2+2?'))
566+
task3 = asyncio.create_task(solver.text('Name of the planet we live on?'))
567+
568+
# Wait for all tasks to complete
569+
results = await asyncio.gather(task1, task2, task3, return_exceptions=True)
570+
return results
571+
572+
# This completes much faster than solving captchas sequentially
573+
results = asyncio.run(solve_multiple_captchas())
574+
```
575+
576+
Examples of solving all supported captcha types asynchronously are located in the [examples/async directory] directory.
577+
578+
### Legacy Async Method
579+
580+
For backward compatibility, you can also use the traditional executor-based approach with the synchronous client:
521581

522582
```python
523583
import asyncio
@@ -535,6 +595,7 @@ async def captchaSolver(image):
535595

536596
captcha_result = asyncio.run(captchaSolver(image))
537597
```
598+
538599
## Examples
539600
Examples of solving all supported captcha types are located in the [examples] directory.
540601

@@ -574,6 +635,8 @@ The graphics and trademarks included in this repository are not covered by the M
574635
[post options]: https://2captcha.com/2captcha-api#normal_post
575636
[list of supported languages]: https://2captcha.com/2captcha-api#language
576637
[examples directory]: /examples
638+
[examples/sync directory]: /examples/sync
639+
[examples/async directory]: /examples/async
577640
[asyncio]: https://docs.python.org/3/library/asyncio.html
578641
[Buy residential proxies]: https://2captcha.com/proxy/residential-proxies
579642
[Quick start]: https://2captcha.com/proxy?openAddTrafficModal=true

examples/async/async_amazon_waf.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import asyncio
2+
import os
3+
import sys
4+
5+
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
6+
7+
from twocaptcha import AsyncTwoCaptcha
8+
9+
# in this example we store the API key inside environment variables that can be set like:
10+
# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS
11+
# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows
12+
# you can just set the API key directly to it's value like:
13+
# api_key="1abc234de56fab7c89012d34e56fa7b8"
14+
15+
api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY')
16+
17+
solver = AsyncTwoCaptcha(api_key)
18+
19+
"""
20+
Important: the values of the 'iv' and 'context' parameters are dynamic, for every request to our API you need to get new values.
21+
The values 'iv' and 'context' need to be looked for in the page code.
22+
"""
23+
24+
25+
async def solve_captcha():
26+
try:
27+
return await solver.amazon_waf(
28+
sitekey='AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AFsClhVgr5q0UFRdXhhHEwiAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMLMbH8d6uQSrYTraoAgEQgDvtSNxdEyG7Zu393cHyPdWNCZgeIB52+W7fCTI8U5z15z1NdPUdnB1ZHoK7ewpwoSMm5mzkJJld0cnvGw==',
29+
iv='CgAAYDJb9CAAACAq',
30+
context='wCho9T9OcETTT8fu1k6+rszr5aGt4eLd+K3mHpV8VbSkjAWJGJx/iQ16RKDCTQBtU5OSeE+SQqoS5iTzhgGtvwgmBbr7X/I+aXaNfb2JRZ8eJ7CnQpM9QRwnv7vGgrGRBGhkh/jaVYmXdy0j0x21s3dCBlA4VN3naDHIweZqkyhXqJBNI1Ep8OMSnhXtPebboB117aBW4IU4XEOii8EE1G4Z7ndWhrNVVXYYwVoxfnSqfYX//CJir6dZfLMbCt5t7NnO8yjsx/YHGVXFVBt2Zrj0ZTxowoYbHU/BKyFaXgUj+ZQ=',
31+
url='https://efw47fpad9.execute-api.us-east-1.amazonaws.com/latest',
32+
)
33+
except Exception as e:
34+
print(e)
35+
return e
36+
37+
38+
if __name__ == '__main__':
39+
result = asyncio.run(solve_captcha())
40+
sys.exit('result: ' + str(result))
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import asyncio
2+
import os
3+
import sys
4+
5+
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
6+
7+
from twocaptcha import AsyncTwoCaptcha
8+
9+
# in this example we store the API key inside environment variables that can be set like:
10+
# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS
11+
# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows
12+
# you can just set the API key directly to it's value like:
13+
# api_key="1abc234de56fab7c89012d34e56fa7b8"
14+
15+
api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY')
16+
17+
config = {
18+
'server': '2captcha.com', # can be also set to 'rucaptcha.com'
19+
'apiKey': api_key,
20+
'softId': 123,
21+
# 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer
22+
'defaultTimeout': 120,
23+
'recaptchaTimeout': 600,
24+
'pollingInterval': 10,
25+
}
26+
27+
solver = AsyncTwoCaptcha(**config)
28+
29+
"""
30+
Important: the values of the 'iv' and 'context' parameters are dynamic, for every request to our API you need to get new values.
31+
The values 'iv' and 'context' need to be looked for in the page code.
32+
"""
33+
34+
35+
async def solve_amazon_waf():
36+
try:
37+
return await solver.amazon_waf(
38+
sitekey='AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AGIqvS8v6ScFa8ZpNRrlQgKAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMx9gxoe10Zg35PWhzAgEQgDvUtMMkqkFQByMLK2329D8iX4mjvaTuUhU70LD4vLp54v3+4K1nYY2hB+OM1hMbncnMbP63y4UOrY77jg==',
39+
iv='CgAGVTNd9JAAAAnB',
40+
context='Lte3LdSjiAN6nNcV0omaNt/ydFmd/eTwRCxYEeuW97LZe3IbAXWi4Er9CWQ3HbDgJ0KSpDgwyoskjKCK4VRQzYufPCdrfCYCveZCt9pMNoAluEtj0oix2GXOPVkw2d4bYOg3MtY5ZUHLR3L467NEInnRE99w5NOgokH5Ie7eOi5sYAqYtZrHABGEgrdAOVvU7bcwvrCERi9wB/WS75geb3oFy6z7Apue9GFa86Ld20jjgy4LWfaen+2fpfKHmCHTKVWfto17Bg+l5i0sr+uFRzpk1We64Fhh1Wl1NHF6M6dpS5s=',
41+
url='https://efw47fpad9.execute-api.us-east-1.amazonaws.com/latest',
42+
challenge_script="https://41bcdd4fb3cb.610cd090.us-east-1.token.awswaf.com/41bcdd4fb3cb/0d21de737ccb/cd77baa6c832/challenge.js",
43+
captcha_script="https://41bcdd4fb3cb.610cd090.us-east-1.captcha.awswaf.com/41bcdd4fb3cb/0d21de737ccb/cd77baa6c832/captcha.js",
44+
callback="https://mysite.com/2captcha.txt"
45+
# proxy={
46+
# 'type': 'HTTPS',
47+
# 'uri': 'login:password@IP_address:PORT'
48+
# }
49+
)
50+
except Exception as e:
51+
print(e)
52+
raise e
53+
54+
55+
if __name__ == '__main__':
56+
try:
57+
result = asyncio.run(solve_amazon_waf())
58+
sys.exit('result: ' + str(result))
59+
except Exception as e:
60+
sys.exit(str(e))
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import asyncio
2+
import os
3+
import sys
4+
5+
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
6+
7+
from twocaptcha import AsyncTwoCaptcha
8+
9+
# in this example we store the API key inside environment variables that can be set like:
10+
# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS
11+
# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows
12+
# you can just set the API key directly to it's value like:
13+
# api_key="1abc234de56fab7c89012d34e56fa7b8"
14+
15+
api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY')
16+
17+
solver = AsyncTwoCaptcha(api_key)
18+
19+
20+
async def solve_captcha():
21+
try:
22+
return await solver.atb_captcha(
23+
app_id='af25e409b33d722a95e56a230ff8771c',
24+
api_server='https://cap.aisecurius.com',
25+
url='http://mysite.com/',
26+
)
27+
except Exception as e:
28+
print(e)
29+
return e
30+
31+
32+
if __name__ == '__main__':
33+
result = asyncio.run(solve_captcha())
34+
sys.exit('result: ' + str(result))
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import asyncio
2+
import os
3+
import sys
4+
5+
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
6+
7+
from twocaptcha import AsyncTwoCaptcha
8+
9+
# in this example we store the API key inside environment variables that can be set like:
10+
# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS
11+
# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows
12+
# you can just set the API key directly to it's value like:
13+
# api_key="1abc234de56fab7c89012d34e56fa7b8"
14+
15+
api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY')
16+
17+
config = {
18+
'server': '2captcha.com', # can be also set to 'rucaptcha.com'
19+
'apiKey': api_key,
20+
'softId': 123,
21+
# 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer
22+
'defaultTimeout': 120,
23+
'recaptchaTimeout': 600,
24+
'pollingInterval': 10,
25+
}
26+
27+
solver = AsyncTwoCaptcha(**config)
28+
29+
30+
async def solve_captcha():
31+
try:
32+
return await solver.atb_captcha(
33+
app_id='af25e409b33d722a95e56a230ff8771c',
34+
api_server='https://cap.aisecurius.com',
35+
url='http://mysite.com/',
36+
# proxy={
37+
# 'type': 'HTTPS',
38+
# 'uri': 'login:password@IP_address:PORT'
39+
# }
40+
)
41+
except Exception as e:
42+
print(e)
43+
return e
44+
45+
46+
if __name__ == '__main__':
47+
result = asyncio.run(solve_captcha())
48+
sys.exit('result: ' + str(result))

examples/async/async_audio.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import asyncio
2+
import os
3+
import sys
4+
5+
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
6+
7+
from twocaptcha import AsyncTwoCaptcha
8+
9+
# in this example we store the API key inside environment variables that can be set like:
10+
# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS
11+
# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows
12+
# you can just set the API key directly to it's value like:
13+
# api_key="1abc234de56fab7c89012d34e56fa7b8"
14+
15+
api_key = os.getenv('APIKEY', 'YOUR_API_KEY')
16+
17+
solver = AsyncTwoCaptcha(api_key)
18+
19+
20+
async def solve_captcha():
21+
try:
22+
return await solver.audio('../audio/example.mp3', lang='en')
23+
except Exception as e:
24+
print(e)
25+
return e
26+
27+
28+
if __name__ == '__main__':
29+
result = asyncio.run(solve_captcha())
30+
sys.exit('result: ' + str(result))

examples/async/async_canvas.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import asyncio
2+
import os
3+
import sys
4+
5+
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
6+
from twocaptcha import AsyncTwoCaptcha
7+
8+
# in this example we store the API key inside environment variables that can be set like:
9+
# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS
10+
# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows
11+
# you can just set the API key directly to it's value like:
12+
# api_key="1abc234de56fab7c89012d34e56fa7b8"
13+
14+
api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY')
15+
16+
solver = AsyncTwoCaptcha(api_key)
17+
18+
19+
async def solve_captcha():
20+
try:
21+
return await solver.canvas('../images/canvas.jpg', hintText='Draw around apple')
22+
except Exception as e:
23+
print(e)
24+
return e
25+
26+
27+
if __name__ == '__main__':
28+
result = asyncio.run(solve_captcha())
29+
sys.exit('result: ' + str(result))
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import asyncio
2+
import os
3+
import sys
4+
from base64 import b64encode
5+
6+
import aiofiles
7+
8+
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
9+
from twocaptcha import AsyncTwoCaptcha
10+
11+
# in this example we store the API key inside environment variables that can be set like:
12+
# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS
13+
# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows
14+
# you can just set the API key directly to it's value like:
15+
# api_key="1abc234de56fab7c89012d34e56fa7b8"
16+
17+
api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY')
18+
19+
solver = AsyncTwoCaptcha(api_key)
20+
21+
22+
async def solve_captcha():
23+
async with aiofiles.open('../images/canvas.jpg', 'rb') as f:
24+
b64 = b64encode(await f.read()).decode('utf-8')
25+
26+
try:
27+
return await solver.canvas(b64, hintText='Draw around apple')
28+
except Exception as e:
29+
print(e)
30+
return e
31+
32+
33+
if __name__ == '__main__':
34+
result = asyncio.run(solve_captcha())
35+
sys.exit('result: ' + str(result))

0 commit comments

Comments
 (0)