diff --git a/README.md b/README.md index 91c7568..b2f072d 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,18 @@ from twocaptcha import TwoCaptcha solver = TwoCaptcha('YOUR_API_KEY') ``` + +
+Async + +```python +from twocaptcha import AsyncTwoCaptcha + +solver = AsyncTwoCaptcha('YOUR_API_KEY') +``` + +
+ Also, there are a few options that can be configured: ```python @@ -517,7 +529,55 @@ proxy={ ``` ## Async calls -You can also make async calls with [asyncio], for example: + +To use the async version, just replace `TwoCaptcha` with `AsyncTwoCaptcha`: + +```python +import asyncio +from twocaptcha import AsyncTwoCaptcha + +async def solve_captcha(): + solver = AsyncTwoCaptcha('YOUR_API_KEY') + + try: + recaptcha_result = await solver.recaptcha(...) + return recaptcha_result + except Exception as e: + print(e) + return None + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) +``` + +The `AsyncTwoCaptcha` class supports all the same methods and parameters as the synchronous `TwoCaptcha` class but operates asynchronously. Configuration is identical. + +### Solving Multiple Captchas in Parallel + +One of the main advantages of using async support is the ability to solve multiple captchas concurrently: + +```python +async def solve_multiple_captchas(): + solver = AsyncTwoCaptcha('YOUR_API_KEY') + + # Start all tasks simultaneously + task1 = asyncio.create_task(solver.text('What color is the sky on a clear day?')) + task2 = asyncio.create_task(solver.text('What is 2+2?')) + task3 = asyncio.create_task(solver.text('Name of the planet we live on?')) + + # Wait for all tasks to complete + results = await asyncio.gather(task1, task2, task3, return_exceptions=True) + return results + +# This completes much faster than solving captchas sequentially +results = asyncio.run(solve_multiple_captchas()) +``` + +Examples of solving all supported captcha types asynchronously are located in the [examples/async directory] directory. + +### Legacy Async Method + +For backward compatibility, you can also use the traditional executor-based approach with the synchronous client: ```python import asyncio @@ -535,6 +595,7 @@ async def captchaSolver(image): captcha_result = asyncio.run(captchaSolver(image)) ``` + ## Examples Examples of solving all supported captcha types are located in the [examples] directory. @@ -574,6 +635,8 @@ The graphics and trademarks included in this repository are not covered by the M [post options]: https://2captcha.com/2captcha-api#normal_post [list of supported languages]: https://2captcha.com/2captcha-api#language [examples directory]: /examples +[examples/sync directory]: /examples/sync +[examples/async directory]: /examples/async [asyncio]: https://docs.python.org/3/library/asyncio.html [Buy residential proxies]: https://2captcha.com/proxy/residential-proxies [Quick start]: https://2captcha.com/proxy?openAddTrafficModal=true diff --git a/examples/async/async_amazon_waf.py b/examples/async/async_amazon_waf.py new file mode 100644 index 0000000..c80e33b --- /dev/null +++ b/examples/async/async_amazon_waf.py @@ -0,0 +1,40 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + +""" +Important: the values of the 'iv' and 'context' parameters are dynamic, for every request to our API you need to get new values. +The values 'iv' and 'context' need to be looked for in the page code. +""" + + +async def solve_captcha(): + try: + return await solver.amazon_waf( + sitekey='AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AFsClhVgr5q0UFRdXhhHEwiAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMLMbH8d6uQSrYTraoAgEQgDvtSNxdEyG7Zu393cHyPdWNCZgeIB52+W7fCTI8U5z15z1NdPUdnB1ZHoK7ewpwoSMm5mzkJJld0cnvGw==', + iv='CgAAYDJb9CAAACAq', + context='wCho9T9OcETTT8fu1k6+rszr5aGt4eLd+K3mHpV8VbSkjAWJGJx/iQ16RKDCTQBtU5OSeE+SQqoS5iTzhgGtvwgmBbr7X/I+aXaNfb2JRZ8eJ7CnQpM9QRwnv7vGgrGRBGhkh/jaVYmXdy0j0x21s3dCBlA4VN3naDHIweZqkyhXqJBNI1Ep8OMSnhXtPebboB117aBW4IU4XEOii8EE1G4Z7ndWhrNVVXYYwVoxfnSqfYX//CJir6dZfLMbCt5t7NnO8yjsx/YHGVXFVBt2Zrj0ZTxowoYbHU/BKyFaXgUj+ZQ=', + url='https://efw47fpad9.execute-api.us-east-1.amazonaws.com/latest', + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_amazon_waf_options.py b/examples/async/async_amazon_waf_options.py new file mode 100644 index 0000000..affff4e --- /dev/null +++ b/examples/async/async_amazon_waf_options.py @@ -0,0 +1,60 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +config = { + 'server': '2captcha.com', # can be also set to 'rucaptcha.com' + 'apiKey': api_key, + 'softId': 123, + # 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer + 'defaultTimeout': 120, + 'recaptchaTimeout': 600, + 'pollingInterval': 10, +} + +solver = AsyncTwoCaptcha(**config) + +""" +Important: the values of the 'iv' and 'context' parameters are dynamic, for every request to our API you need to get new values. +The values 'iv' and 'context' need to be looked for in the page code. +""" + + +async def solve_amazon_waf(): + try: + return await solver.amazon_waf( + sitekey='AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AGIqvS8v6ScFa8ZpNRrlQgKAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMx9gxoe10Zg35PWhzAgEQgDvUtMMkqkFQByMLK2329D8iX4mjvaTuUhU70LD4vLp54v3+4K1nYY2hB+OM1hMbncnMbP63y4UOrY77jg==', + iv='CgAGVTNd9JAAAAnB', + context='Lte3LdSjiAN6nNcV0omaNt/ydFmd/eTwRCxYEeuW97LZe3IbAXWi4Er9CWQ3HbDgJ0KSpDgwyoskjKCK4VRQzYufPCdrfCYCveZCt9pMNoAluEtj0oix2GXOPVkw2d4bYOg3MtY5ZUHLR3L467NEInnRE99w5NOgokH5Ie7eOi5sYAqYtZrHABGEgrdAOVvU7bcwvrCERi9wB/WS75geb3oFy6z7Apue9GFa86Ld20jjgy4LWfaen+2fpfKHmCHTKVWfto17Bg+l5i0sr+uFRzpk1We64Fhh1Wl1NHF6M6dpS5s=', + url='https://efw47fpad9.execute-api.us-east-1.amazonaws.com/latest', + challenge_script="https://41bcdd4fb3cb.610cd090.us-east-1.token.awswaf.com/41bcdd4fb3cb/0d21de737ccb/cd77baa6c832/challenge.js", + captcha_script="https://41bcdd4fb3cb.610cd090.us-east-1.captcha.awswaf.com/41bcdd4fb3cb/0d21de737ccb/cd77baa6c832/captcha.js", + callback="https://mysite.com/2captcha.txt" + # proxy={ + # 'type': 'HTTPS', + # 'uri': 'login:password@IP_address:PORT' + # } + ) + except Exception as e: + print(e) + raise e + + +if __name__ == '__main__': + try: + result = asyncio.run(solve_amazon_waf()) + sys.exit('result: ' + str(result)) + except Exception as e: + sys.exit(str(e)) diff --git a/examples/async/async_atb_captcha.py b/examples/async/async_atb_captcha.py new file mode 100644 index 0000000..c4b4432 --- /dev/null +++ b/examples/async/async_atb_captcha.py @@ -0,0 +1,34 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.atb_captcha( + app_id='af25e409b33d722a95e56a230ff8771c', + api_server='https://cap.aisecurius.com', + url='http://mysite.com/', + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_atb_captcha_options.py b/examples/async/async_atb_captcha_options.py new file mode 100644 index 0000000..d9163cb --- /dev/null +++ b/examples/async/async_atb_captcha_options.py @@ -0,0 +1,48 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +config = { + 'server': '2captcha.com', # can be also set to 'rucaptcha.com' + 'apiKey': api_key, + 'softId': 123, + # 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer + 'defaultTimeout': 120, + 'recaptchaTimeout': 600, + 'pollingInterval': 10, +} + +solver = AsyncTwoCaptcha(**config) + + +async def solve_captcha(): + try: + return await solver.atb_captcha( + app_id='af25e409b33d722a95e56a230ff8771c', + api_server='https://cap.aisecurius.com', + url='http://mysite.com/', + # proxy={ + # 'type': 'HTTPS', + # 'uri': 'login:password@IP_address:PORT' + # } + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_audio.py b/examples/async/async_audio.py new file mode 100644 index 0000000..65b8395 --- /dev/null +++ b/examples/async/async_audio.py @@ -0,0 +1,30 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.audio('../audio/example.mp3', lang='en') + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_canvas.py b/examples/async/async_canvas.py new file mode 100644 index 0000000..3d62b01 --- /dev/null +++ b/examples/async/async_canvas.py @@ -0,0 +1,29 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.canvas('../images/canvas.jpg', hintText='Draw around apple') + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_canvas_base64.py b/examples/async/async_canvas_base64.py new file mode 100644 index 0000000..fc9f647 --- /dev/null +++ b/examples/async/async_canvas_base64.py @@ -0,0 +1,35 @@ +import asyncio +import os +import sys +from base64 import b64encode + +import aiofiles + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + async with aiofiles.open('../images/canvas.jpg', 'rb') as f: + b64 = b64encode(await f.read()).decode('utf-8') + + try: + return await solver.canvas(b64, hintText='Draw around apple') + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_canvas_options.py b/examples/async/async_canvas_options.py new file mode 100644 index 0000000..e0f329a --- /dev/null +++ b/examples/async/async_canvas_options.py @@ -0,0 +1,37 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key, defaultTimeout=120, pollingInterval=5, server='2captcha.com') + + +async def solve_captcha(): + try: + return await solver.canvas( + '../images/canvas.jpg', + previousId=0, + canSkip=0, + lang='en', + hintImg='../images/canvas_hint.jpg', + hintText='Draw around apple', + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_capy.py b/examples/async/async_capy.py new file mode 100644 index 0000000..8232dc4 --- /dev/null +++ b/examples/async/async_capy.py @@ -0,0 +1,34 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.capy( + sitekey='PUZZLE_Cz04hZLjuZRMYC3ee10C32D3uNms5w', + url='https://www.mysite.com/page/captcha/', + api_server="https://jp.api.capy.me/", + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_capy_options.py b/examples/async/async_capy_options.py new file mode 100644 index 0000000..87d1cdc --- /dev/null +++ b/examples/async/async_capy_options.py @@ -0,0 +1,33 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key, defaultTimeout=30, pollingInterval=5) + + +async def solve_captcha(): + try: + return await solver.capy(sitekey='PUZZLE_Cz04hZLjuZRMYC3ee10C32D3uNms5w', + url='https://www.mysite.com/captcha/', + api_server="https://jp.api.capy.me/", + softId=33112) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_coordinates.py b/examples/async/async_coordinates.py new file mode 100644 index 0000000..0deb48f --- /dev/null +++ b/examples/async/async_coordinates.py @@ -0,0 +1,30 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.coordinates('../images/grid.jpg') + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_coordinates_base64.py b/examples/async/async_coordinates_base64.py new file mode 100644 index 0000000..32c5be7 --- /dev/null +++ b/examples/async/async_coordinates_base64.py @@ -0,0 +1,36 @@ +import asyncio +import os +import sys +from base64 import b64encode + +import aiofiles + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + async with aiofiles.open('../images/grid.jpg', 'rb') as f: + b64 = b64encode(await f.read()).decode('utf-8') + + try: + return await solver.coordinates(b64) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_coordinates_options.py b/examples/async/async_coordinates_options.py new file mode 100644 index 0000000..06f8131 --- /dev/null +++ b/examples/async/async_coordinates_options.py @@ -0,0 +1,35 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key, defaultTimeout=120, pollingInterval=5, extendedResponse=True) + + +async def solve_captcha(): + try: + return await solver.coordinates('../images/grid_2.jpg', + lang='en', + hintImg='../images/grid_hint.jpg', + hintText='Select all images with an Orange', + min_clicks=2, + max_clicks=3) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_cutcaptcha.py b/examples/async/async_cutcaptcha.py new file mode 100644 index 0000000..1b3351a --- /dev/null +++ b/examples/async/async_cutcaptcha.py @@ -0,0 +1,34 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.cutcaptcha( + misery_key='ad52c87af17e2ec09b8d918c9f00416b1cb8c320', + apikey='SAs61IAI', + url='https://mysite.com/page/with/cutcaptcha', + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_cutcaptcha_options.py b/examples/async/async_cutcaptcha_options.py new file mode 100644 index 0000000..edfcd72 --- /dev/null +++ b/examples/async/async_cutcaptcha_options.py @@ -0,0 +1,47 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +config = { + 'server': '2captcha.com', # can be also set to 'rucaptcha.com' + 'apiKey': api_key, + 'softId': 123, + # 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer + 'defaultTimeout': 120, + 'recaptchaTimeout': 600, + 'pollingInterval': 10, +} + +solver = AsyncTwoCaptcha(**config) + + +async def solve_captcha(): + try: + return await solver.cutcaptcha(misery_key='ad52c87af17e2ec09b8d918c9f00416b1cb8c320', + apikey='SAs61IAI', + url='https://mysite.com/page/with/cutcaptcha' + # proxy={ + # 'type': 'HTTPS', + # 'uri': 'login:password@IP_address:PORT' + # } + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_cybersiara.py b/examples/async/async_cybersiara.py new file mode 100644 index 0000000..93b4c7c --- /dev/null +++ b/examples/async/async_cybersiara.py @@ -0,0 +1,34 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.cybersiara( + master_url_id='tpjOCKjjpdzv3d8Ub2E9COEWKt1vl1Mv', + pageurl='https://demo.mycybersiara.com/', + userAgent='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_datadome.py b/examples/async/async_datadome.py new file mode 100644 index 0000000..c1ff46f --- /dev/null +++ b/examples/async/async_datadome.py @@ -0,0 +1,38 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.datadome( + captcha_url="https://geo.captcha-delivery.com/captcha/?initialCid=AHrlqAAAAAMAZirHgKBVrxwAsVuKlQ%3D%3D&c...", + pageurl="https://mysite.com/page/with/datadome", + userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36", + proxy={ + 'type': 'HTTP', + 'uri': 'login:password@IP_address:PORT' + } + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_friendly_captcha.py b/examples/async/async_friendly_captcha.py new file mode 100644 index 0000000..9987380 --- /dev/null +++ b/examples/async/async_friendly_captcha.py @@ -0,0 +1,33 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.friendly_captcha( + sitekey='FCMGEMUD2KTDSQ5H', + url='https://friendlycaptcha.com/demo', + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_friendly_captcha_options.py b/examples/async/async_friendly_captcha_options.py new file mode 100644 index 0000000..38e24d1 --- /dev/null +++ b/examples/async/async_friendly_captcha_options.py @@ -0,0 +1,47 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +config = { + 'server': '2captcha.com', # can be also set to 'rucaptcha.com' + 'apiKey': api_key, + 'softId': 123, + # 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer + 'defaultTimeout': 120, + 'recaptchaTimeout': 600, + 'pollingInterval': 10, +} + +solver = AsyncTwoCaptcha(**config) + + +async def solve_captcha(): + try: + return await solver.friendly_captcha( + sitekey='FCMGEMUD2KTDSQ5H', + url='https://friendlycaptcha.com/demo', + # proxy={ + # 'type': 'HTTPS', + # 'uri': 'login:password@IP_address:PORT' + # } + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_funcaptcha.py b/examples/async/async_funcaptcha.py new file mode 100644 index 0000000..844999a --- /dev/null +++ b/examples/async/async_funcaptcha.py @@ -0,0 +1,34 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.funcaptcha( + sitekey='69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC', + url='https://mysite.com/page/with/funcaptcha', + surl='https://client-api.arkoselabs.com' + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_funcaptcha_options.py b/examples/async/async_funcaptcha_options.py new file mode 100644 index 0000000..2af81a2 --- /dev/null +++ b/examples/async/async_funcaptcha_options.py @@ -0,0 +1,40 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key, defaultTimeout=180, pollingInterval=15) + + +async def solve_captcha(): + try: + return await solver.funcaptcha( + sitekey='FB18D9DB-BAFF-DDAC-A33B-6CF22267BC0A', + url='https://mysite.com/page/with/funcaptcha', + surl='https://client-api.arkoselabs.com', + userAgent= + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', + **{'data[key]': 'value'}, # optional data param used by some websites + proxy={ + 'type': 'HTTP', + 'uri': 'login:password@123.123.123.123:8080' + }) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_geetest.py b/examples/async/async_geetest.py new file mode 100644 index 0000000..dd7a214 --- /dev/null +++ b/examples/async/async_geetest.py @@ -0,0 +1,45 @@ +import asyncio +import os +import sys + +import requests + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + +""" +Important: the value of the 'challenge' parameter is dynamic, for each request to our API you need to get a new value. +""" + + +async def solve_captcha(): + # Get the challenge - keeping this synchronous since it's just setup + resp = requests.get("https://2captcha.com/api/v1/captcha-demo/gee-test/init-params") + challenge = resp.json()['challenge'] + + try: + return await solver.geetest( + gt='81388ea1fc187e0c335c0a8907ff2625', + apiServer='http://api.geetest.com', + challenge=challenge, + url='https://2captcha.com/demo/geetest' + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_geetest_options.py b/examples/async/async_geetest_options.py new file mode 100644 index 0000000..ffb0d41 --- /dev/null +++ b/examples/async/async_geetest_options.py @@ -0,0 +1,49 @@ +import asyncio +import os +import sys + +import requests + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key, defaultTimeout=300, pollingInterval=10, extendedResponse=True) + +""" +Important: the value of the 'challenge' parameter is dynamic, for each request to our API you need to get a new value. +""" + + +async def solve_captcha(): + # Get the challenge - we keep this synchronous since it's just setup + resp = requests.get("https://2captcha.com/api/v1/captcha-demo/gee-test/init-params") + challenge = resp.json()['challenge'] + + try: + return await solver.geetest( + gt='81388ea1fc187e0c335c0a8907ff2625', + apiServer='http://api.geetest.com', + challenge=challenge, + url='https://2captcha.com/demo/geetest', + # proxy={ + # 'type': 'HTTPS', + # 'uri': 'login:password@IP_address:PORT' + # } + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_geetest_v4.py b/examples/async/async_geetest_v4.py new file mode 100644 index 0000000..6f5857f --- /dev/null +++ b/examples/async/async_geetest_v4.py @@ -0,0 +1,33 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.geetest_v4( + captcha_id='e392e1d7fd421dc63325744d5a2b9c73', + url='https://2captcha.com/demo/geetest-v4' + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_geetest_v4_options.py b/examples/async/async_geetest_v4_options.py new file mode 100644 index 0000000..7a07b3c --- /dev/null +++ b/examples/async/async_geetest_v4_options.py @@ -0,0 +1,47 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +config = { + 'server': '2captcha.com', # can be also set to 'rucaptcha.com' + 'apiKey': api_key, + 'softId': 123, + # 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer + 'defaultTimeout': 120, + 'recaptchaTimeout': 600, + 'pollingInterval': 10, +} + +solver = AsyncTwoCaptcha(**config) + + +async def solve_captcha(): + try: + return await solver.geetest_v4( + captcha_id='e392e1d7fd421dc63325744d5a2b9c73', + url='https://2captcha.com/demo/geetest-v4', + # proxy={ + # 'type': 'HTTPS', + # 'uri': 'login:password@IP_address:PORT' + # } + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_grid.py b/examples/async/async_grid.py new file mode 100644 index 0000000..e41a43f --- /dev/null +++ b/examples/async/async_grid.py @@ -0,0 +1,35 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.grid( + '../images/grid_2.jpg', + hintText='Select all images with an Orange', + rows=3, + cols=3 + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_grid_base64.py b/examples/async/async_grid_base64.py new file mode 100644 index 0000000..76f7c47 --- /dev/null +++ b/examples/async/async_grid_base64.py @@ -0,0 +1,42 @@ +import asyncio +import os +import sys +from base64 import b64encode + +import aiofiles + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + # Read file and convert to base64 + async with aiofiles.open('../images/grid_2.jpg', 'rb') as f: + b64 = b64encode(await f.read()).decode('utf-8') + + try: + return await solver.grid( + b64, + hintText='Select all images with an Orange', + rows=3, + cols=3 + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_grid_options.py b/examples/async/async_grid_options.py new file mode 100644 index 0000000..8f3cf74 --- /dev/null +++ b/examples/async/async_grid_options.py @@ -0,0 +1,39 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key, defaultTimeout=100, pollingInterval=12) + + +async def solve_captcha(): + try: + return await solver.grid( + file='../images/grid_2.jpg', + rows=3, + cols=3, + previousId=0, + canSkip=0, + lang='en', + hintImg='../images/grid_hint.jpg', + # hintText='Select all images with an Orange', + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_keycaptcha.py b/examples/async/async_keycaptcha.py new file mode 100644 index 0000000..3854f75 --- /dev/null +++ b/examples/async/async_keycaptcha.py @@ -0,0 +1,36 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.keycaptcha( + s_s_c_user_id=184015, + s_s_c_session_id='e34ddd2c72e67593ac0b4ca8e4f44725', + s_s_c_web_server_sign='a5ebd41ae22348b2cdbdc211792e982d', + s_s_c_web_server_sign2='29255689423dd92990f8d06de50560d0', + url='https://2captcha.com/demo/keycaptcha' + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_keycaptcha_options.py b/examples/async/async_keycaptcha_options.py new file mode 100644 index 0000000..746b749 --- /dev/null +++ b/examples/async/async_keycaptcha_options.py @@ -0,0 +1,48 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +config = { + 'server': '2captcha.com', # can be also set to 'rucaptcha.com' + 'apiKey': api_key, + 'softId': 123, + # 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer + 'defaultTimeout': 120, + 'recaptchaTimeout': 600, + 'pollingInterval': 10, +} + +solver = AsyncTwoCaptcha(**config) + + +async def solve_captcha(): + try: + return await solver.keycaptcha( + s_s_c_user_id=184015, + s_s_c_session_id='e34ddd2c72e67593ac0b4ca8e4f44725', + s_s_c_web_server_sign='a5ebd41ae22348b2cdbdc211792e982d', + s_s_c_web_server_sign2='29255689423dd92990f8d06de50560d0', + url='https://2captcha.com/demo/keycaptcha', + # proxy = {'type': 'HTTPS', + # 'uri': 'login:password@IP_address:PORT'} + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_lemin.py b/examples/async/async_lemin.py new file mode 100644 index 0000000..e119664 --- /dev/null +++ b/examples/async/async_lemin.py @@ -0,0 +1,34 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.lemin( + captcha_id='CROPPED_5a29582_ca114c2f3314482c84cd32fc7d2feb63', + div_id='lemin-cropped-captcha', + url='https://2captcha.com/demo/lemin' + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_mtcaptcha.py b/examples/async/async_mtcaptcha.py new file mode 100644 index 0000000..a704ffe --- /dev/null +++ b/examples/async/async_mtcaptcha.py @@ -0,0 +1,33 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.mtcaptcha( + sitekey='MTPublic-KzqLY1cKH', + url='https://2captcha.com/demo/mtcaptcha', + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_mtcaptcha_options.py b/examples/async/async_mtcaptcha_options.py new file mode 100644 index 0000000..83dc416 --- /dev/null +++ b/examples/async/async_mtcaptcha_options.py @@ -0,0 +1,47 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +config = { + 'server': '2captcha.com', # can be also set to 'rucaptcha.com' + 'apiKey': api_key, + 'softId': 123, + # 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer + 'defaultTimeout': 120, + 'recaptchaTimeout': 600, + 'pollingInterval': 10, +} + +solver = AsyncTwoCaptcha(**config) + + +async def solve_captcha(): + try: + return await solver.mtcaptcha( + sitekey='MTPublic-KzqLY1cKH', + url='https://2captcha.com/demo/mtcaptcha', + # proxy={ + # 'type': 'HTTPS', + # 'uri': 'login:password@IP_address:PORT' + # } + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_normal.py b/examples/async/async_normal.py new file mode 100644 index 0000000..3089252 --- /dev/null +++ b/examples/async/async_normal.py @@ -0,0 +1,30 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.normal('../images/normal.jpg') + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_normal_base64.py b/examples/async/async_normal_base64.py new file mode 100644 index 0000000..2a03e82 --- /dev/null +++ b/examples/async/async_normal_base64.py @@ -0,0 +1,36 @@ +import asyncio +import os +import sys +from base64 import b64encode + +import aiofiles + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + async with aiofiles.open('../images/normal.jpg', 'rb') as f: + b64 = b64encode(await f.read()).decode('utf-8') + + try: + return await solver.normal(b64) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_normal_options.py b/examples/async/async_normal_options.py new file mode 100644 index 0000000..89855ec --- /dev/null +++ b/examples/async/async_normal_options.py @@ -0,0 +1,41 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key, defaultTimeout=30, pollingInterval=5) + + +async def solve_captcha(): + try: + return await solver.normal( + '../images/normal_2.jpg', + numeric=4, + minLen=4, + maxLen=20, + phrase=0, + caseSensitive=0, + calc=0, + lang='en', + # hintImg='../images/normal_hint.jpg', + # hintText='Type red symbols only', + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_recaptcha_v2.py b/examples/async/async_recaptcha_v2.py new file mode 100644 index 0000000..3da9566 --- /dev/null +++ b/examples/async/async_recaptcha_v2.py @@ -0,0 +1,32 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.recaptcha( + sitekey='6LdO5_IbAAAAAAeVBL9TClS19NUTt5wswEb3Q7C5', + url='https://2captcha.com/demo/recaptcha-v2-invisible') + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_recaptcha_v2_options.py b/examples/async/async_recaptcha_v2_options.py new file mode 100644 index 0000000..88cfeaa --- /dev/null +++ b/examples/async/async_recaptcha_v2_options.py @@ -0,0 +1,49 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +config = { + 'server': '2captcha.com', # can be also set to 'rucaptcha.com' + 'apiKey': api_key, + 'softId': 123, + # 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer + 'defaultTimeout': 120, + 'recaptchaTimeout': 600, + 'pollingInterval': 10, +} + +solver = AsyncTwoCaptcha(**config) + + +async def solve_captcha(): + try: + return await solver.recaptcha( + sitekey='6LdO5_IbAAAAAAeVBL9TClS19NUTt5wswEb3Q7C5', + url='https://2captcha.com/demo/recaptcha-v2-invisible', + invisible=1, + enterprise=0, + # datas="bM-8CwwOmqyYCLWatmabvfyYR97ytF95tgu...", + # proxy={'type': 'HTTPS', + # 'uri': 'login:password@IP_address:PORT' + # } + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_recaptcha_v3.py b/examples/async/async_recaptcha_v3.py new file mode 100644 index 0000000..1705127 --- /dev/null +++ b/examples/async/async_recaptcha_v3.py @@ -0,0 +1,34 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.recaptcha( + sitekey='6LfdxboZAAAAAMtnONIt4DJ8J1t4wMC-kVG02zIO', + url='https://2captcha.com/demo/recaptcha-v3', + action='login', + version='v3') + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_recaptcha_v3_options.py b/examples/async/async_recaptcha_v3_options.py new file mode 100644 index 0000000..0d5ba6b --- /dev/null +++ b/examples/async/async_recaptcha_v3_options.py @@ -0,0 +1,51 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +config = { + 'server': '2captcha.com', # can be also set to 'rucaptcha.com' + 'apiKey': api_key, + 'softId': 123, + # 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer + 'defaultTimeout': 120, + 'recaptchaTimeout': 600, + 'pollingInterval': 10, +} + +solver = AsyncTwoCaptcha(**config) + + +async def solve_captcha(): + try: + return await solver.recaptcha( + sitekey='6LfdxboZAAAAAMtnONIt4DJ8J1t4wMC-kVG02zIO', + url='https://2captcha.com/demo/recaptcha-v3', + version='v3', + enterprise=0, + action='verify', + score=0.7 + # proxy={ + # 'type': 'HTTPS', + # 'uri': 'login:password@IP_address:PORT' + # } + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_rotate.py b/examples/async/async_rotate.py new file mode 100644 index 0000000..cf90851 --- /dev/null +++ b/examples/async/async_rotate.py @@ -0,0 +1,30 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.rotate('../images/rotate.jpg') + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_rotate_options.py b/examples/async/async_rotate_options.py new file mode 100644 index 0000000..930489c --- /dev/null +++ b/examples/async/async_rotate_options.py @@ -0,0 +1,35 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key, defaultTimeout=100, pollingInterval=10) + + +async def solve_captcha(): + try: + return await solver.rotate( + '../images/rotate.jpg', + angle=40, + lang='en', + # hintImg = '../images/rotate_hint.jpg' + hintText='Put the images in the correct way up') + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_tencent.py b/examples/async/async_tencent.py new file mode 100644 index 0000000..20e7b3c --- /dev/null +++ b/examples/async/async_tencent.py @@ -0,0 +1,33 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.tencent( + app_id="913522596", + url="https://mysite.com/page/with/tencent" + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_tencent_options.py b/examples/async/async_tencent_options.py new file mode 100644 index 0000000..4c26b50 --- /dev/null +++ b/examples/async/async_tencent_options.py @@ -0,0 +1,47 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +config = { + 'server': '2captcha.com', # can be also set to 'rucaptcha.com' + 'apiKey': api_key, + 'softId': 123, + # 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer + 'defaultTimeout': 120, + 'recaptchaTimeout': 600, + 'pollingInterval': 10, +} + +solver = AsyncTwoCaptcha(**config) + + +async def solve_captcha(): + try: + return await solver.tencent( + app_id="197325555", + url="https://your.site/result-receiver", + # proxy={ + # 'type': 'HTTPS', + # 'uri': 'ub6900fef552505bc-zone-custom-session-JcIHpmDKv-sessTime-1:ub6900fef552505bc@43.152.113.55:2333' + # } + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_text.py b/examples/async/async_text.py new file mode 100644 index 0000000..c1fcdfb --- /dev/null +++ b/examples/async/async_text.py @@ -0,0 +1,30 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.text('If tomorrow is Saturday, what day is today?') + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_text_options.py b/examples/async/async_text_options.py new file mode 100644 index 0000000..2bf0e01 --- /dev/null +++ b/examples/async/async_text_options.py @@ -0,0 +1,31 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key, defaultTimeout=40, pollingInterval=10) + + +async def solve_captcha(): + try: + return await solver.text('If tomorrow is Saturday, what day is today?', + lang='en') + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_turnstile.py b/examples/async/async_turnstile.py new file mode 100644 index 0000000..f303d67 --- /dev/null +++ b/examples/async/async_turnstile.py @@ -0,0 +1,33 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.turnstile( + sitekey='0x4AAAAAAAVrOwQWPlm3Bnr5', + url='https://2captcha.com/demo/cloudflare-turnstile', + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_turnstile_options.py b/examples/async/async_turnstile_options.py new file mode 100644 index 0000000..54fcc8b --- /dev/null +++ b/examples/async/async_turnstile_options.py @@ -0,0 +1,51 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +config = { + 'server': '2captcha.com', # can be also set to 'rucaptcha.com' + 'apiKey': api_key, + 'softId': 123, + # 'callback': 'https://your.site/result-receiver', # if set, sovler with just return captchaId, not polling API for the answer + 'defaultTimeout': 120, + 'recaptchaTimeout': 600, + 'pollingInterval': 10, +} + +solver = AsyncTwoCaptcha(**config) + + +async def solve_captcha(): + try: + return await solver.turnstile( + sitekey='0x4AAAAAAAVrOwQWPlm3Bnr5', + url='https://2captcha.com/demo/cloudflare-turnstile', + # data="str", + # pagedata="str", + # action="str", + # useragent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" + # proxy={ + # 'type': 'HTTPS', + # 'uri': 'login:password@IP_address:PORT' + # } + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_yandex_smart.py b/examples/async/async_yandex_smart.py new file mode 100644 index 0000000..c3b2198 --- /dev/null +++ b/examples/async/async_yandex_smart.py @@ -0,0 +1,33 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +solver = AsyncTwoCaptcha(api_key) + + +async def solve_captcha(): + try: + return await solver.yandex_smart( + sitekey="FEXfAbHQsToo97VidNVk3j4dC74nGW1DgdxK4OoR", + url="https://www.site.com/page/" + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/async/async_yandex_smart_options.py b/examples/async/async_yandex_smart_options.py new file mode 100644 index 0000000..5305ada --- /dev/null +++ b/examples/async/async_yandex_smart_options.py @@ -0,0 +1,47 @@ +import asyncio +import os +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) + +from twocaptcha import AsyncTwoCaptcha + +# in this example we store the API key inside environment variables that can be set like: +# export APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Linux or macOS +# set APIKEY_2CAPTCHA=1abc234de56fab7c89012d34e56fa7b8 on Windows +# you can just set the API key directly to it's value like: +# api_key="1abc234de56fab7c89012d34e56fa7b8" + +api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY') + +config = { + 'server': '2captcha.com', # can be also set to 'rucaptcha.com' + 'apiKey': api_key, + 'softId': 123, + # 'callback': 'https://your.site/result-receiver', # if set, solver with just return captchaId, not polling API for the answer + 'defaultTimeout': 120, + 'recaptchaTimeout': 600, + 'pollingInterval': 10, +} + +solver = AsyncTwoCaptcha(**config) + + +async def solve_captcha(): + try: + return await solver.yandex_smart( + sitekey="FEXfAbHQsToo97VidNVk3j4dC74nGW1DgdxK4OoR", + url="https://www.site.com/page/", + # proxy={ + # 'type': 'HTTPS', + # 'uri': 'login:password@IP_address:PORT' + # } + ) + except Exception as e: + print(e) + return e + + +if __name__ == '__main__': + result = asyncio.run(solve_captcha()) + sys.exit('result: ' + str(result)) diff --git a/examples/amazon_waf.py b/examples/sync/amazon_waf.py similarity index 92% rename from examples/amazon_waf.py rename to examples/sync/amazon_waf.py index 3a79e0c..80486b3 100644 --- a/examples/amazon_waf.py +++ b/examples/sync/amazon_waf.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -29,7 +29,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/amazon_waf_options.py b/examples/sync/amazon_waf_options.py similarity index 95% rename from examples/amazon_waf_options.py rename to examples/sync/amazon_waf_options.py index 31c6d92..aa0b6a7 100644 --- a/examples/amazon_waf_options.py +++ b/examples/sync/amazon_waf_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -46,7 +46,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/atb_captcha.py b/examples/sync/atb_captcha.py similarity index 86% rename from examples/atb_captcha.py rename to examples/sync/atb_captcha.py index 1cfb664..07a0b39 100644 --- a/examples/atb_captcha.py +++ b/examples/sync/atb_captcha.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -23,7 +23,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/atb_captcha_options.py b/examples/sync/atb_captcha_options.py similarity index 92% rename from examples/atb_captcha_options.py rename to examples/sync/atb_captcha_options.py index 379c7ce..cd275d3 100644 --- a/examples/atb_captcha_options.py +++ b/examples/sync/atb_captcha_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -37,7 +37,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/audio.py b/examples/sync/audio.py similarity index 75% rename from examples/audio.py rename to examples/sync/audio.py index 29ffebd..b05ae16 100644 --- a/examples/audio.py +++ b/examples/sync/audio.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -16,10 +16,10 @@ solver = TwoCaptcha(api_key) try: - result = solver.audio('./audio/example.mp3', lang='en') + result = solver.audio('../audio/example.mp3', lang='en') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/canvas.py b/examples/sync/canvas.py similarity index 73% rename from examples/canvas.py rename to examples/sync/canvas.py index 7eae4bc..9060274 100644 --- a/examples/canvas.py +++ b/examples/sync/canvas.py @@ -1,6 +1,6 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha # in this example we store the API key inside environment variables that can be set like: @@ -14,10 +14,10 @@ solver = TwoCaptcha(api_key) try: - result = solver.canvas('./images/canvas.jpg', hintText='Draw around apple') + result = solver.canvas('../images/canvas.jpg', hintText='Draw around apple') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/canvas_base64.py b/examples/sync/canvas_base64.py similarity index 81% rename from examples/canvas_base64.py rename to examples/sync/canvas_base64.py index 2736dea..201715f 100644 --- a/examples/canvas_base64.py +++ b/examples/sync/canvas_base64.py @@ -2,7 +2,7 @@ import os from base64 import b64encode -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha # in this example we store the API key inside environment variables that can be set like: @@ -15,14 +15,14 @@ solver = TwoCaptcha(api_key) -with open('./images/canvas.jpg', 'rb') as f: +with open('../images/canvas.jpg', 'rb') as f: b64 = b64encode(f.read()).decode('utf-8') try: result = solver.canvas(b64, hintText='Draw around apple') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/canvas_options.py b/examples/sync/canvas_options.py similarity index 79% rename from examples/canvas_options.py rename to examples/sync/canvas_options.py index 6c29f6b..875a861 100644 --- a/examples/canvas_options.py +++ b/examples/sync/canvas_options.py @@ -1,6 +1,6 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -16,16 +16,16 @@ try: result = solver.canvas( - './images/canvas.jpg', + '../images/canvas.jpg', previousId=0, canSkip=0, lang='en', - hintImg='./images/canvas_hint.jpg', + hintImg='../images/canvas_hint.jpg', hintText='Draw around apple', ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/capy.py b/examples/sync/capy.py similarity index 86% rename from examples/capy.py rename to examples/sync/capy.py index 78fdde1..8bf5277 100644 --- a/examples/capy.py +++ b/examples/sync/capy.py @@ -1,6 +1,6 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -22,7 +22,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/capy_options.py b/examples/sync/capy_options.py similarity index 87% rename from examples/capy_options.py rename to examples/sync/capy_options.py index d9bc90a..522b308 100644 --- a/examples/capy_options.py +++ b/examples/sync/capy_options.py @@ -1,6 +1,6 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -21,7 +21,7 @@ softId=33112) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/coordinates.py b/examples/sync/coordinates.py similarity index 76% rename from examples/coordinates.py rename to examples/sync/coordinates.py index d0f3626..41523b3 100644 --- a/examples/coordinates.py +++ b/examples/sync/coordinates.py @@ -1,6 +1,6 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -15,10 +15,10 @@ solver = TwoCaptcha(api_key) try: - result = solver.coordinates('./images/grid.jpg') + result = solver.coordinates('../images/grid.jpg') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/coordinates_base64.py b/examples/sync/coordinates_base64.py similarity index 80% rename from examples/coordinates_base64.py rename to examples/sync/coordinates_base64.py index 783e7ce..48b4e9c 100644 --- a/examples/coordinates_base64.py +++ b/examples/sync/coordinates_base64.py @@ -2,7 +2,7 @@ import os from base64 import b64encode -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -16,14 +16,14 @@ solver = TwoCaptcha(api_key) -with open('./images/grid.jpg', 'rb') as f: +with open('../images/grid.jpg', 'rb') as f: b64 = b64encode(f.read()).decode('utf-8') try: result = solver.coordinates(b64) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/coordinates_options.py b/examples/sync/coordinates_options.py similarity index 77% rename from examples/coordinates_options.py rename to examples/sync/coordinates_options.py index e88c8ab..b7f746e 100644 --- a/examples/coordinates_options.py +++ b/examples/sync/coordinates_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -16,14 +16,14 @@ solver = TwoCaptcha(api_key, defaultTimeout=120, pollingInterval=5, extendedResponse=True) try: - result = solver.coordinates('./images/grid_2.jpg', + result = solver.coordinates('../images/grid_2.jpg', lang='en', - hintImg='./images/grid_hint.jpg', + hintImg='../images/grid_hint.jpg', hintText='Select all images with an Orange', min_clicks=2, max_clicks=3) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/cutcaptcha.py b/examples/sync/cutcaptcha.py similarity index 86% rename from examples/cutcaptcha.py rename to examples/sync/cutcaptcha.py index 11acedf..d60802e 100644 --- a/examples/cutcaptcha.py +++ b/examples/sync/cutcaptcha.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -24,7 +24,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) \ No newline at end of file diff --git a/examples/cutcaptcha_options.py b/examples/sync/cutcaptcha_options.py similarity index 92% rename from examples/cutcaptcha_options.py rename to examples/sync/cutcaptcha_options.py index a1cb2c5..fea8264 100644 --- a/examples/cutcaptcha_options.py +++ b/examples/sync/cutcaptcha_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -36,7 +36,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) \ No newline at end of file diff --git a/examples/cybersiara.py b/examples/sync/cybersiara.py similarity index 87% rename from examples/cybersiara.py rename to examples/sync/cybersiara.py index a8604c6..d7ab50f 100644 --- a/examples/cybersiara.py +++ b/examples/sync/cybersiara.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -24,7 +24,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) \ No newline at end of file diff --git a/examples/datadome.py b/examples/sync/datadome.py similarity index 89% rename from examples/datadome.py rename to examples/sync/datadome.py index 7a62980..2c376ce 100644 --- a/examples/datadome.py +++ b/examples/sync/datadome.py @@ -1,8 +1,7 @@ -import sys import os -import json +import sys -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -28,7 +27,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) \ No newline at end of file diff --git a/examples/friendly_captcha.py b/examples/sync/friendly_captcha.py similarity index 85% rename from examples/friendly_captcha.py rename to examples/sync/friendly_captcha.py index 29d1a92..c98d8ff 100644 --- a/examples/friendly_captcha.py +++ b/examples/sync/friendly_captcha.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -22,7 +22,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) \ No newline at end of file diff --git a/examples/friendly_captcha_options.py b/examples/sync/friendly_captcha_options.py similarity index 91% rename from examples/friendly_captcha_options.py rename to examples/sync/friendly_captcha_options.py index 9203ef5..9e731f5 100644 --- a/examples/friendly_captcha_options.py +++ b/examples/sync/friendly_captcha_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -35,7 +35,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) \ No newline at end of file diff --git a/examples/funcaptcha.py b/examples/sync/funcaptcha.py similarity index 87% rename from examples/funcaptcha.py rename to examples/sync/funcaptcha.py index 28a0aa9..c8b101b 100644 --- a/examples/funcaptcha.py +++ b/examples/sync/funcaptcha.py @@ -1,6 +1,6 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -20,7 +20,7 @@ surl='https://client-api.arkoselabs.com') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/funcaptcha_options.py b/examples/sync/funcaptcha_options.py similarity index 90% rename from examples/funcaptcha_options.py rename to examples/sync/funcaptcha_options.py index a79dab7..c4f0d14 100644 --- a/examples/funcaptcha_options.py +++ b/examples/sync/funcaptcha_options.py @@ -1,6 +1,6 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -28,7 +28,7 @@ }) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/geetest.py b/examples/sync/geetest.py similarity index 90% rename from examples/geetest.py rename to examples/sync/geetest.py index 2819a29..c069f84 100644 --- a/examples/geetest.py +++ b/examples/sync/geetest.py @@ -1,7 +1,7 @@ import sys import os import requests -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -29,7 +29,7 @@ url='https://2captcha.com/demo/geetest') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) \ No newline at end of file diff --git a/examples/geetest_options.py b/examples/sync/geetest_options.py similarity index 91% rename from examples/geetest_options.py rename to examples/sync/geetest_options.py index 35e74a8..791233e 100644 --- a/examples/geetest_options.py +++ b/examples/sync/geetest_options.py @@ -1,7 +1,7 @@ import sys import os import requests -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -35,7 +35,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) \ No newline at end of file diff --git a/examples/geetest_v4.py b/examples/sync/geetest_v4.py similarity index 85% rename from examples/geetest_v4.py rename to examples/sync/geetest_v4.py index 2aea352..b4682d1 100644 --- a/examples/geetest_v4.py +++ b/examples/sync/geetest_v4.py @@ -1,7 +1,7 @@ -import sys import os -import requests -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -20,7 +20,7 @@ url='https://2captcha.com/demo/geetest-v4') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/geetest_v4_options.py b/examples/sync/geetest_v4_options.py similarity index 92% rename from examples/geetest_v4_options.py rename to examples/sync/geetest_v4_options.py index 1a32ef0..c0b6791 100644 --- a/examples/geetest_v4_options.py +++ b/examples/sync/geetest_v4_options.py @@ -1,7 +1,7 @@ -import sys import os -import requests -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +import sys + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -35,7 +35,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/grid.py b/examples/sync/grid.py similarity index 80% rename from examples/grid.py rename to examples/sync/grid.py index 6a459a2..13241a8 100644 --- a/examples/grid.py +++ b/examples/sync/grid.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -16,13 +16,13 @@ solver = TwoCaptcha(api_key) try: - result = solver.grid('./images/grid_2.jpg', + result = solver.grid('../images/grid_2.jpg', hintText='Select all images with an Orange', rows=3, cols=3) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/grid_base64.py b/examples/sync/grid_base64.py similarity index 83% rename from examples/grid_base64.py rename to examples/sync/grid_base64.py index 36194ab..8a4c1be 100644 --- a/examples/grid_base64.py +++ b/examples/sync/grid_base64.py @@ -2,7 +2,7 @@ import os from base64 import b64encode -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -16,7 +16,7 @@ solver = TwoCaptcha(api_key) -with open('./images/grid_2.jpg', 'rb') as f: +with open('../images/grid_2.jpg', 'rb') as f: b64 = b64encode(f.read()).decode('utf-8') try: @@ -26,7 +26,7 @@ cols=3) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/grid_options.py b/examples/sync/grid_options.py similarity index 79% rename from examples/grid_options.py rename to examples/sync/grid_options.py index d17060a..645d386 100644 --- a/examples/grid_options.py +++ b/examples/sync/grid_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -17,18 +17,18 @@ try: result = solver.grid( - file='./images/grid_2.jpg', + file='../images/grid_2.jpg', rows=3, cols=3, previousId=0, canSkip=0, lang='en', - hintImg='./images/grid_hint.jpg', + hintImg='../images/grid_hint.jpg', # hintText='Select all images with an Orange', ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/keycaptcha.py b/examples/sync/keycaptcha.py similarity index 88% rename from examples/keycaptcha.py rename to examples/sync/keycaptcha.py index f6d9c4b..824b3f1 100644 --- a/examples/keycaptcha.py +++ b/examples/sync/keycaptcha.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -24,7 +24,7 @@ url='https://2captcha.com/demo/keycaptcha') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/keycaptcha_options.py b/examples/sync/keycaptcha_options.py similarity index 93% rename from examples/keycaptcha_options.py rename to examples/sync/keycaptcha_options.py index a04bbbc..00f623f 100644 --- a/examples/keycaptcha_options.py +++ b/examples/sync/keycaptcha_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -38,7 +38,7 @@ except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/lemin.py b/examples/sync/lemin.py similarity index 87% rename from examples/lemin.py rename to examples/sync/lemin.py index 18ac536..ec01bcf 100644 --- a/examples/lemin.py +++ b/examples/sync/lemin.py @@ -1,6 +1,6 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -21,7 +21,7 @@ except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/mtcaptcha.py b/examples/sync/mtcaptcha.py similarity index 85% rename from examples/mtcaptcha.py rename to examples/sync/mtcaptcha.py index d1aa862..01a7e52 100644 --- a/examples/mtcaptcha.py +++ b/examples/sync/mtcaptcha.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -22,7 +22,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) \ No newline at end of file diff --git a/examples/mtcaptcha_options.py b/examples/sync/mtcaptcha_options.py similarity index 91% rename from examples/mtcaptcha_options.py rename to examples/sync/mtcaptcha_options.py index 0935fa6..6781f81 100644 --- a/examples/mtcaptcha_options.py +++ b/examples/sync/mtcaptcha_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -35,7 +35,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) \ No newline at end of file diff --git a/examples/normal.py b/examples/sync/normal.py similarity index 76% rename from examples/normal.py rename to examples/sync/normal.py index cb856de..805719e 100644 --- a/examples/normal.py +++ b/examples/sync/normal.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -16,10 +16,10 @@ solver = TwoCaptcha(api_key) try: - result = solver.normal('./images/normal.jpg') + result = solver.normal('../images/normal.jpg') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/normal_base64.py b/examples/sync/normal_base64.py similarity index 80% rename from examples/normal_base64.py rename to examples/sync/normal_base64.py index ef25d25..6a4de73 100644 --- a/examples/normal_base64.py +++ b/examples/sync/normal_base64.py @@ -2,7 +2,7 @@ import os from base64 import b64encode -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -16,14 +16,14 @@ solver = TwoCaptcha(api_key) -with open('./images/normal.jpg', 'rb') as f: +with open('../images/normal.jpg', 'rb') as f: b64 = b64encode(f.read()).decode('utf-8') try: result = solver.normal(b64) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/normal_options.py b/examples/sync/normal_options.py similarity index 80% rename from examples/normal_options.py rename to examples/sync/normal_options.py index 2cc797f..45d2d9e 100644 --- a/examples/normal_options.py +++ b/examples/sync/normal_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -17,7 +17,7 @@ try: result = solver.normal( - './images/normal_2.jpg', + '../images/normal_2.jpg', numeric=4, minLen=4, maxLen=20, @@ -25,12 +25,12 @@ caseSensitive=0, calc=0, lang='en', - # hintImg='./images/normal_hint.jpg', + # hintImg='../images/normal_hint.jpg', # hintText='Type red symbols only', ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/recaptcha_v2.py b/examples/sync/recaptcha_v2.py similarity index 85% rename from examples/recaptcha_v2.py rename to examples/sync/recaptcha_v2.py index 660ab55..996f921 100644 --- a/examples/recaptcha_v2.py +++ b/examples/sync/recaptcha_v2.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -21,7 +21,7 @@ url='https://2captcha.com/demo/recaptcha-v2-invisible') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/recaptcha_v2_options.py b/examples/sync/recaptcha_v2_options.py similarity index 92% rename from examples/recaptcha_v2_options.py rename to examples/sync/recaptcha_v2_options.py index a803edb..202958f 100644 --- a/examples/recaptcha_v2_options.py +++ b/examples/sync/recaptcha_v2_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -39,7 +39,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/recaptcha_v3.py b/examples/sync/recaptcha_v3.py similarity index 86% rename from examples/recaptcha_v3.py rename to examples/sync/recaptcha_v3.py index eabc2a8..1d7af8e 100644 --- a/examples/recaptcha_v3.py +++ b/examples/sync/recaptcha_v3.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -23,7 +23,7 @@ version='v3') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/recaptcha_v3_options.py b/examples/sync/recaptcha_v3_options.py similarity index 91% rename from examples/recaptcha_v3_options.py rename to examples/sync/recaptcha_v3_options.py index 9218a7f..8301adc 100644 --- a/examples/recaptcha_v3_options.py +++ b/examples/sync/recaptcha_v3_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -41,7 +41,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/rotate.py b/examples/sync/rotate.py similarity index 76% rename from examples/rotate.py rename to examples/sync/rotate.py index 0af275a..b073c11 100644 --- a/examples/rotate.py +++ b/examples/sync/rotate.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -16,10 +16,10 @@ solver = TwoCaptcha(api_key) try: - result = solver.rotate('./images/rotate.jpg') + result = solver.rotate('../images/rotate.jpg') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/rotate_options.py b/examples/sync/rotate_options.py similarity index 87% rename from examples/rotate_options.py rename to examples/sync/rotate_options.py index ddd2311..a5b55e0 100644 --- a/examples/rotate_options.py +++ b/examples/sync/rotate_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -24,7 +24,7 @@ hintText='Put the images in the correct way up') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/tencent.py b/examples/sync/tencent.py similarity index 85% rename from examples/tencent.py rename to examples/sync/tencent.py index 9854141..50d36dd 100644 --- a/examples/tencent.py +++ b/examples/sync/tencent.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -22,7 +22,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) \ No newline at end of file diff --git a/examples/tencent_options.py b/examples/sync/tencent_options.py similarity index 92% rename from examples/tencent_options.py rename to examples/sync/tencent_options.py index da33ca9..ca1c6a5 100644 --- a/examples/tencent_options.py +++ b/examples/sync/tencent_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -36,7 +36,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/text.py b/examples/sync/text.py similarity index 84% rename from examples/text.py rename to examples/sync/text.py index 4a5b4a2..8be4bfd 100644 --- a/examples/text.py +++ b/examples/sync/text.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -19,7 +19,7 @@ result = solver.text('If tomorrow is Saturday, what day is today?') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: print(result) diff --git a/examples/text_options.py b/examples/sync/text_options.py similarity index 85% rename from examples/text_options.py rename to examples/sync/text_options.py index c55410a..f4b8fef 100644 --- a/examples/text_options.py +++ b/examples/sync/text_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -20,7 +20,7 @@ lang='en') except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/turnstile.py b/examples/sync/turnstile.py similarity index 85% rename from examples/turnstile.py rename to examples/sync/turnstile.py index 2466b39..6735b0c 100644 --- a/examples/turnstile.py +++ b/examples/sync/turnstile.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -22,7 +22,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/turnstile_options.py b/examples/sync/turnstile_options.py similarity index 93% rename from examples/turnstile_options.py rename to examples/sync/turnstile_options.py index 15a4ddf..d9cb360 100644 --- a/examples/turnstile_options.py +++ b/examples/sync/turnstile_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -40,7 +40,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/examples/yandex_smart.py b/examples/sync/yandex_smart.py similarity index 85% rename from examples/yandex_smart.py rename to examples/sync/yandex_smart.py index a8eb4c4..3a17431 100644 --- a/examples/yandex_smart.py +++ b/examples/sync/yandex_smart.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -22,7 +22,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) \ No newline at end of file diff --git a/examples/yandex_smart_options.py b/examples/sync/yandex_smart_options.py similarity index 92% rename from examples/yandex_smart_options.py rename to examples/sync/yandex_smart_options.py index 3a8b548..2436215 100644 --- a/examples/yandex_smart_options.py +++ b/examples/sync/yandex_smart_options.py @@ -1,7 +1,7 @@ import sys import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) from twocaptcha import TwoCaptcha @@ -36,7 +36,7 @@ ) except Exception as e: - sys.exit(e) + sys.exit(str(e)) else: sys.exit('result: ' + str(result)) diff --git a/requirements.txt b/requirements.txt index 1480256..8ef20de 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,3 @@ -requests>=2.20.0 \ No newline at end of file +requests>=2.20.0 +httpx>=0.28.1 +aiofiles>=24.1.0 \ No newline at end of file diff --git a/setup.py b/setup.py index 5026fe1..7ba1dff 100644 --- a/setup.py +++ b/setup.py @@ -3,12 +3,12 @@ from setuptools import setup, find_packages import re -with open("README.md", "r") as fh: +with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read() def get_version(): - with open('twocaptcha/__init__.py', 'r') as f: + with open('twocaptcha/__init__.py', 'r', encoding="utf-8") as f: return re.search(r'__version__ = ["\'](.*?)["\']', f.read()).group(1) @@ -18,7 +18,7 @@ def get_version(): long_description=long_description, long_description_content_type="text/markdown", url='https://github.com/2captcha/2captcha-python/', - install_requires=['requests'], + install_requires=['requests', 'httpx', 'aiofiles'], author='2Captcha', author_email='info@2captcha.com', packages=find_packages(), diff --git a/tests/async/abstract_async.py b/tests/async/abstract_async.py new file mode 100644 index 0000000..ece4ae1 --- /dev/null +++ b/tests/async/abstract_async.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +import asyncio +import os +import sys +import unittest + +sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) + +from twocaptcha import AsyncTwoCaptcha + +captcha_id = '123' +code = 'abcd' + + +class AsyncApiClient(): + async def in_(self, files={}, **kwargs): + self.incomings = kwargs + self.incoming_files = files + + return 'OK|' + captcha_id + + async def res(self, **kwargs): + return 'OK|' + code # {'code': code} + + +class AsyncAbstractTest(unittest.TestCase): + def setUp(self): + self.solver = AsyncTwoCaptcha('API_KEY', pollingInterval=1) + self.solver.api_client = AsyncApiClient() + + def send_return(self, for_send, method, **kwargs): + asyncio.run(self._async_send_return(for_send, method, **kwargs)) + + async def _async_send_return(self, for_send, method, **kwargs): + file = kwargs.pop('file', {}) + file = kwargs.pop('files', file) + + result = await method(file, **kwargs) if file else await method(**kwargs) + + incomings = self.solver.api_client.incomings + for_send.update({'key': 'API_KEY'}) + for_send.update({'soft_id': 4580}) + + files = for_send.pop('files', {}) + self.assertEqual(incomings, for_send) + + incoming_files = self.solver.api_client.incoming_files + incoming_files and self.assertEqual(incoming_files, files) + + self.assertIsInstance(result, dict) + self.assertIn('code', result) + self.assertEqual(result['code'], code) + + def invalid_file(self, method, **kwargs): + asyncio.run(self._async_invalid_file(method, **kwargs)) + + async def _async_invalid_file(self, method, **kwargs): + with self.assertRaises(self.solver.exceptions): + await method('lost_file', **kwargs) + + def too_many_files(self, method, **kwargs): + asyncio.run(self._async_too_many_files(method, **kwargs)) + + async def _async_too_many_files(self, method, **kwargs): + files = ['../../examples/images/rotate.jpg'] * (self.solver.max_files + 1) + with self.assertRaises(self.solver.exceptions): + await method(files, **kwargs) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/canvas_async_test.py b/tests/async/canvas_async_test.py new file mode 100644 index 0000000..c2bea9e --- /dev/null +++ b/tests/async/canvas_async_test.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 + +import unittest + +file = '../../examples/images/canvas.jpg' +hint_img = '../../examples/images/canvas_hint.jpg' +hint = 'Draw around apple' + +try: + from .abstract_async import AsyncAbstractTest + + file = file[3:] + hint_img = hint_img[3:] +except ImportError: + from abstract_async import AsyncAbstractTest + +checks = {'canvas': 1, 'recaptcha': 1, 'textinstructions': hint} + + +class AsyncCanvasTest(AsyncAbstractTest): + def test_file_param(self): + sends = {'method': 'post', 'file': file, **checks} + return self.send_return(sends, + self.solver.canvas, + file=file, + hintText=hint) + + def test_base64_param(self): + b64 = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + sends = { + 'method': 'base64', + 'body': b64, + **checks, + } + + return self.send_return(sends, + self.solver.canvas, + file=b64, + hintText=hint) + + def test_all_params(self): + params = { + 'previousId': 0, + 'canSkip': 0, + 'lang': 'en', + 'hintImg': hint_img, + 'hintText': hint + } + + sends = { + 'method': 'post', + 'previousID': 0, + 'can_no_answer': 0, + 'lang': 'en', + 'files': { + 'file': file, + 'imginstructions': hint_img + }, + **checks + } + + return self.send_return(sends, self.solver.canvas, file=file, **params) + + def test_not_found(self): + return self.invalid_file(self.solver.canvas, hintText=hint) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_amazon_waf.py b/tests/async/test_async_amazon_waf.py new file mode 100644 index 0000000..7fc071b --- /dev/null +++ b/tests/async/test_async_amazon_waf.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncAmazonWAFTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'sitekey': 'AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AFsClhVgr5q0UFRdXhhHEwiAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMLMbH8d6uQSrYTraoAgEQgDvtSNxdEyG7Zu393cHyPdWNCZgeIB52+W7fCTI8U5z15z1NdPUdnB1ZHoK7ewpwoSMm5mzkJJld0cnvGw==', + 'url': 'https://www.site.com/page/', + 'iv': 'CgAAYDJb9CAAACAq', + 'context': 'wCho9T9OcETTT8fu1k6+rszr5aGt4eLd+K3mHpV8VbSkjAWJGJx/iQ16RKDCTQBtU5OSeE+SQqoS5iTzhgGtvwgmBbr7X/I+aXaNfb2JRZ8eJ7CnQpM9QRwnv7vGgrGRBGhkh/jaVYmXdy0j0x21s3dCBlA4VN3naDHIweZqkyhXqJBNI1Ep8OMSnhXtPebboB117aBW4IU4XEOii8EE1G4Z7ndWhrNVVXYYwVoxfnSqfYX//CJir6dZfLMbCt5t7NnO8yjsx/YHGVXFVBt2Zrj0ZTxowoYbHU/BKyFaXgUj+ZQ=' + } + + sends = { + 'method': 'amazon_waf', + 'sitekey': 'AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AFsClhVgr5q0UFRdXhhHEwiAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMLMbH8d6uQSrYTraoAgEQgDvtSNxdEyG7Zu393cHyPdWNCZgeIB52+W7fCTI8U5z15z1NdPUdnB1ZHoK7ewpwoSMm5mzkJJld0cnvGw==', + 'iv': 'CgAAYDJb9CAAACAq', + 'context': 'wCho9T9OcETTT8fu1k6+rszr5aGt4eLd+K3mHpV8VbSkjAWJGJx/iQ16RKDCTQBtU5OSeE+SQqoS5iTzhgGtvwgmBbr7X/I+aXaNfb2JRZ8eJ7CnQpM9QRwnv7vGgrGRBGhkh/jaVYmXdy0j0x21s3dCBlA4VN3naDHIweZqkyhXqJBNI1Ep8OMSnhXtPebboB117aBW4IU4XEOii8EE1G4Z7ndWhrNVVXYYwVoxfnSqfYX//CJir6dZfLMbCt5t7NnO8yjsx/YHGVXFVBt2Zrj0ZTxowoYbHU/BKyFaXgUj+ZQ=', + 'pageurl': 'https://www.site.com/page/', + } + + return self.send_return(sends, self.solver.amazon_waf, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_atb_captcha.py b/tests/async/test_async_atb_captcha.py new file mode 100644 index 0000000..0d5ad78 --- /dev/null +++ b/tests/async/test_async_atb_captcha.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncAtbCaptchaTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'app_id': 'af25e409b33d722a95e56a230ff8771c', + 'api_server': 'https://cap.aisecurius.com', + 'url': 'http://mysite.com/' + } + + sends = { + 'method': 'atb_captcha', + 'app_id': 'af25e409b33d722a95e56a230ff8771c', + 'api_server': 'https://cap.aisecurius.com', + 'pageurl': 'http://mysite.com/' + } + + self.send_return(sends, self.solver.atb_captcha, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_canvas.py b/tests/async/test_async_canvas.py new file mode 100644 index 0000000..1a2147d --- /dev/null +++ b/tests/async/test_async_canvas.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 + +import unittest + +file = '../examples/images/canvas.jpg' +hint = 'Draw around apple' +hint_img = '../examples/images/canvas_hint.jpg' + +checks = {'canvas': 1, 'recaptcha': 1, 'textinstructions': hint} + +try: + from .abstract_async import AsyncAbstractTest + +except ImportError: + from abstract_async import AsyncAbstractTest + + file = file[3:] + hint_img = hint_img[3:] + + +class AsyncCanvasTest(AsyncAbstractTest): + def test_file_param(self): + sends = {'method': 'post', 'file': file, **checks} + self.send_return(sends, self.solver.canvas, file=file, hintText=hint) + + def test_base64_param(self): + b64 = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + sends = { + 'method': 'base64', + 'body': b64, + **checks, + } + + self.send_return(sends, self.solver.canvas, file=b64, hintText=hint) + + def test_all_params(self): + params = { + 'previousId': 0, + 'canSkip': 0, + 'lang': 'en', + 'hintImg': hint_img, + 'hintText': hint + } + + sends = { + 'method': 'post', + 'previousID': 0, + 'can_no_answer': 0, + 'lang': 'en', + 'files': {'file': file, 'imginstructions': hint_img}, + **checks + } + + self.send_return(sends, self.solver.canvas, file=file, **params) + + def test_not_found(self): + self.invalid_file(self.solver.canvas, hintText=hint) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_capy.py b/tests/async/test_async_capy.py new file mode 100644 index 0000000..3519a7d --- /dev/null +++ b/tests/async/test_async_capy.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncCapyTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'sitekey': 'PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v', + 'url': 'http://mysite.com/', + } + + sends = { + 'method': 'capy', + 'captchakey': 'PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v', + 'pageurl': 'http://mysite.com/', + } + + self.send_return(sends, self.solver.capy, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_coordinates.py b/tests/async/test_async_coordinates.py new file mode 100644 index 0000000..b2031a7 --- /dev/null +++ b/tests/async/test_async_coordinates.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 + +import unittest + +file = '../examples/images/grid.jpg' +hint_img = '../examples/images/grid_hint.jpg' +hint_text = 'Select all images with an Orange' +checks = {'coordinatescaptcha': 1} + +try: + from .abstract_async import AsyncAbstractTest + +except ImportError: + from abstract_async import AsyncAbstractTest + + file = file[3:] + hint_img = hint_img[3:] + + +class AsyncCoordinatesTest(AsyncAbstractTest): + def test_file_param(self): + sends = {'method': 'post', 'file': file, **checks} + self.send_return(sends, self.solver.coordinates, file=file) + + def test_base64_param(self): + b64 = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + sends = { + 'method': 'base64', + 'body': b64, + **checks, + } + + self.send_return(sends, self.solver.coordinates, file=b64) + + def test_all_params(self): + params = { + 'lang': 'en', + 'hintImg': hint_img, + 'hintText': hint_text + } + + sends = { + 'method': 'post', + 'lang': 'en', + 'files': {'file': file, 'imginstructions': hint_img}, + 'textinstructions': hint_text, + **checks + } + + self.send_return(sends, self.solver.coordinates, file=file, **params) + + def test_not_found(self): + self.invalid_file(self.solver.coordinates) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_cutcaptcha.py b/tests/async/test_async_cutcaptcha.py new file mode 100644 index 0000000..5580fd4 --- /dev/null +++ b/tests/async/test_async_cutcaptcha.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncCutcaptchaTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'misery_key': 'ad52c87af17e2ec09b8d918c9f00416b1cb8c320', + 'apikey': 'SAs61IAI', + 'url': 'https://www.site.com/page/', + } + + sends = { + 'method': 'cutcaptcha', + 'api_key': 'SAs61IAI', + 'misery_key': 'ad52c87af17e2ec09b8d918c9f00416b1cb8c320', + 'pageurl': 'https://www.site.com/page/', + } + + self.send_return(sends, self.solver.cutcaptcha, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_cybersiara.py b/tests/async/test_async_cybersiara.py new file mode 100644 index 0000000..8b5a6be --- /dev/null +++ b/tests/async/test_async_cybersiara.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncCybersiaraTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'master_url_id': 'tpjOCKjjpdzv3d8Ub2E9COEWKt1vl1Mv', + 'pageurl': 'https://demo.mycybersiara.com/', + 'userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', + } + + sends = { + 'method': 'cybersiara', + 'master_url_id': 'tpjOCKjjpdzv3d8Ub2E9COEWKt1vl1Mv', + 'pageurl': 'https://demo.mycybersiara.com/', + 'userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', + } + + self.send_return(sends, self.solver.cybersiara, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_datadome.py b/tests/async/test_async_datadome.py new file mode 100644 index 0000000..7064d4a --- /dev/null +++ b/tests/async/test_async_datadome.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncDatadomeTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'captcha_url': 'https://geo.captcha-delivery.com/captcha/?initialCid=AHrlqAAAAAMAZirHgKBVrxwAsVuKlQ%3D%3D&c', + 'pageurl': 'https://mysite.com/page/with/datadome', + 'userAgent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', + 'proxy': {'type': 'HTTP', 'uri': 'login:password@IP_address:PORT'} + } + + sends = { + 'method': 'datadome', + 'captcha_url': 'https://geo.captcha-delivery.com/captcha/?initialCid=AHrlqAAAAAMAZirHgKBVrxwAsVuKlQ%3D%3D&c', + 'pageurl': 'https://mysite.com/page/with/datadome', + 'userAgent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', + 'proxy': 'login:password@IP_address:PORT', + 'proxytype': 'HTTP' + } + + self.send_return(sends, self.solver.datadome, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_friendly_captcha.py b/tests/async/test_async_friendly_captcha.py new file mode 100644 index 0000000..f89e8f6 --- /dev/null +++ b/tests/async/test_async_friendly_captcha.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncFriendlyCaptchaTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'sitekey': 'FCMGEMUD2KTDSQ5H', + 'url': 'https://friendlycaptcha.com/demo', + } + + sends = { + 'method': 'friendly_captcha', + 'sitekey': 'FCMGEMUD2KTDSQ5H', + 'pageurl': 'https://friendlycaptcha.com/demo', + } + + self.send_return(sends, self.solver.friendly_captcha, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_funcaptcha.py b/tests/async/test_async_funcaptcha.py new file mode 100644 index 0000000..4891a99 --- /dev/null +++ b/tests/async/test_async_funcaptcha.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncFuncaptchaTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'sitekey': '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC', + 'url': 'https://mysite.com/page/with/funcaptcha', + 'surl': 'https://client-api.arkoselabs.com', + 'userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', + 'data': {'anyKey': 'anyStringValue'}, + } + + sends = { + 'method': 'funcaptcha', + 'publickey': '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC', + 'pageurl': 'https://mysite.com/page/with/funcaptcha', + 'surl': 'https://client-api.arkoselabs.com', + 'userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', + 'data': {'anyKey': 'anyStringValue'}, + } + + self.send_return(sends, self.solver.funcaptcha, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_geetest.py b/tests/async/test_async_geetest.py new file mode 100644 index 0000000..605359f --- /dev/null +++ b/tests/async/test_async_geetest.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncGeeTestTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'gt': 'f2ae6cadcf7886856696502e1d55e00c', + 'apiServer': 'api-na.geetest.com', + 'challenge': '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC', + 'url': 'https://launches.endclothing.com/distil_r_captcha.html', + } + + sends = { + 'method': 'geetest', + 'gt': 'f2ae6cadcf7886856696502e1d55e00c', + 'api_server': 'api-na.geetest.com', + 'challenge': '69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC', + 'pageurl': 'https://launches.endclothing.com/distil_r_captcha.html', + } + + self.send_return(sends, self.solver.geetest, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_geetest_v4.py b/tests/async/test_async_geetest_v4.py new file mode 100644 index 0000000..4b1b524 --- /dev/null +++ b/tests/async/test_async_geetest_v4.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncGeeTestV4Test(AsyncAbstractTest): + def test_all_params(self): + params = { + 'captcha_id': 'e392e1d7fd421dc63325744d5a2b9c73', + 'url': 'https://2captcha.com/demo/geetest-v4', + } + + sends = { + 'method': 'geetest_v4', + 'captcha_id': 'e392e1d7fd421dc63325744d5a2b9c73', + 'pageurl': 'https://2captcha.com/demo/geetest-v4', + } + + self.send_return(sends, self.solver.geetest_v4, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_grid.py b/tests/async/test_async_grid.py new file mode 100644 index 0000000..9245191 --- /dev/null +++ b/tests/async/test_async_grid.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 + +import unittest + +file = '../examples/images/grid.jpg' +hint_img = '../examples/images/grid_hint.jpg' +hint_text = 'Select all images with an Orange' + +try: + from .abstract_async import AsyncAbstractTest + +except ImportError: + from abstract_async import AsyncAbstractTest + + file = file[3:] + hint_img = hint_img[3:] + + +class AsyncGridTest(AsyncAbstractTest): + def test_file_param(self): + sends = {'method': 'post', 'file': file, 'recaptcha': 1} + self.send_return(sends, self.solver.grid, file=file) + + def test_base64_param(self): + b64 = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + sends = { + 'method': 'base64', + 'body': b64, + 'recaptcha': 1 + } + + self.send_return(sends, self.solver.grid, file=b64) + + def test_all_params(self): + params = { + 'rows': 3, + 'cols': 3, + 'previousId': 0, + 'canSkip': 0, + 'lang': 'en', + 'hintImg': hint_img, + 'hintText': hint_text + } + + sends = { + 'method': 'post', + 'recaptcha': 1, + 'recaptcharows': 3, + 'recaptchacols': 3, + 'previousID': 0, + 'can_no_answer': 0, + 'lang': 'en', + 'files': {'file': file, 'imginstructions': hint_img}, + 'textinstructions': hint_text, + } + + self.send_return(sends, self.solver.grid, file=file, **params) + + def test_not_found(self): + self.invalid_file(self.solver.grid) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_hcaptcha.py b/tests/async/test_async_hcaptcha.py new file mode 100644 index 0000000..ca915d2 --- /dev/null +++ b/tests/async/test_async_hcaptcha.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncHcaptchaTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'sitekey': 'f1ab2cdefa3456789012345b6c78d90e', + 'url': 'https://www.site.com/page/', + } + + sends = { + 'method': 'hcaptcha', + 'sitekey': 'f1ab2cdefa3456789012345b6c78d90e', + 'pageurl': 'https://www.site.com/page/', + } + + self.send_return(sends, self.solver.hcaptcha, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_keycaptcha.py b/tests/async/test_async_keycaptcha.py new file mode 100644 index 0000000..3d7ac86 --- /dev/null +++ b/tests/async/test_async_keycaptcha.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncKeyCaptchaTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 's_s_c_user_id': 10, + 's_s_c_session_id': '493e52c37c10c2bcdf4a00cbc9ccd1e8', + 's_s_c_web_server_sign': '9006dc725760858e4c0715b835472f22-pz-', + 's_s_c_web_server_sign2': '2ca3abe86d90c6142d5571db98af6714', + 'url': 'https://www.keycaptcha.ru/demo-magnetic/', + } + + sends = { + 'method': 'keycaptcha', + 's_s_c_user_id': 10, + 's_s_c_session_id': '493e52c37c10c2bcdf4a00cbc9ccd1e8', + 's_s_c_web_server_sign': '9006dc725760858e4c0715b835472f22-pz-', + 's_s_c_web_server_sign2': '2ca3abe86d90c6142d5571db98af6714', + 'pageurl': 'https://www.keycaptcha.ru/demo-magnetic/', + } + + self.send_return(sends, self.solver.keycaptcha, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_lemin.py b/tests/async/test_async_lemin.py new file mode 100644 index 0000000..7305fd5 --- /dev/null +++ b/tests/async/test_async_lemin.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncLeminTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'captcha_id': 'CROPPED_1abcd2f_a1234b567c890d12ef3a456bc78d901d', + 'div_id': 'lemin-cropped-captcha', + 'api_server': 'https://api.leminnow.com/', + 'url': 'http://mysite.com/', + } + + sends = { + 'method': 'lemin', + 'captcha_id': 'CROPPED_1abcd2f_a1234b567c890d12ef3a456bc78d901d', + 'div_id': 'lemin-cropped-captcha', + 'api_server': 'https://api.leminnow.com/', + 'pageurl': 'http://mysite.com/', + } + + self.send_return(sends, self.solver.lemin, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_mtcaptcha.py b/tests/async/test_async_mtcaptcha.py new file mode 100644 index 0000000..661c54d --- /dev/null +++ b/tests/async/test_async_mtcaptcha.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncMTCaptchaTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'sitekey': 'MTPublic-KzqLY1cKH', + 'url': 'https://2captcha.com/demo/mtcaptcha', + } + + sends = { + 'method': 'mt_captcha', + 'sitekey': 'MTPublic-KzqLY1cKH', + 'pageurl': 'https://2captcha.com/demo/mtcaptcha', + } + + self.send_return(sends, self.solver.mtcaptcha, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_normal.py b/tests/async/test_async_normal.py new file mode 100644 index 0000000..69e5d2d --- /dev/null +++ b/tests/async/test_async_normal.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +import unittest + +file = '../examples/images/normal.jpg' +hint_img = '../examples/images/grid_hint.jpg' + +try: + from .abstract_async import AsyncAbstractTest + +except ImportError: + from abstract_async import AsyncAbstractTest + + file = file[3:] + hint_img = hint_img[3:] + + +class AsyncNormalTest(AsyncAbstractTest): + def test_file(self): + sends = {'method': 'post', 'file': file} + self.send_return(sends, self.solver.normal, file=file) + + def test_base64(self): + b64 = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + sends = { + 'method': 'base64', + 'body': b64, + } + + self.send_return(sends, self.solver.normal, file=b64) + + def test_all_params(self): + params = { + 'numeric': 4, + 'minLen': 4, + 'maxLen': 20, + 'phrase': 1, + 'caseSensitive': 1, + 'calc': 0, + 'lang': 'en', + 'hintImg': hint_img, + 'hintText': 'Type red symbols only', + } + + sends = { + 'files': {'file': file, 'imginstructions': hint_img}, + 'method': 'post', + 'numeric': 4, + 'min_len': 4, + 'max_len': 20, + 'phrase': 1, + 'regsense': 1, + 'calc': 0, + 'lang': 'en', + 'textinstructions': 'Type red symbols only', + } + + self.send_return(sends, self.solver.normal, file=file, **params) + + def test_not_found(self): + self.invalid_file(self.solver.normal) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_recaptcha.py b/tests/async/test_async_recaptcha.py new file mode 100644 index 0000000..e3576ac --- /dev/null +++ b/tests/async/test_async_recaptcha.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncRecaptchaTest(AsyncAbstractTest): + def test_v2(self): + params = { + 'sitekey': '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-', + 'url': 'https://mysite.com/page/with/recaptcha', + 'invisible': 1, + 'action': 'verify', + 'datas': 'Crb7VsRAQaBqoaQQtHQQ' + } + + sends = { + 'method': 'userrecaptcha', + 'googlekey': '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-', + 'pageurl': 'https://mysite.com/page/with/recaptcha', + 'invisible': 1, + 'enterprise': 0, + 'action': 'verify', + 'version': 'v2', + 'data-s': 'Crb7VsRAQaBqoaQQtHQQ' + } + + self.send_return(sends, self.solver.recaptcha, **params) + + def test_v3(self): + params = { + 'sitekey': '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-', + 'url': 'https://mysite.com/page/with/recaptcha', + 'invisible': 1, + 'action': 'verify', + 'version': 'v3', + } + + sends = { + 'method': 'userrecaptcha', + 'googlekey': '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-', + 'pageurl': 'https://mysite.com/page/with/recaptcha', + 'invisible': 1, + 'enterprise': 0, + 'action': 'verify', + 'version': 'v3', + } + + self.send_return(sends, self.solver.recaptcha, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_rotate.py b/tests/async/test_async_rotate.py new file mode 100644 index 0000000..c4cafa0 --- /dev/null +++ b/tests/async/test_async_rotate.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +import unittest + +files = ['../examples/images/rotate.jpg'] + +hint_img = '../examples/images/grid_hint.jpg' +hint_text = 'Put the images in the correct way up' + +try: + from .abstract_async import AsyncAbstractTest + +except ImportError: + from abstract_async import AsyncAbstractTest + + files = [f[3:] for f in files] + hint_img = hint_img[3:] + +files_dict = {f'file_{e + 1}': f for e, f in enumerate(files)} + +checks = {'method': 'rotatecaptcha'} + + +class AsyncRotateTest(AsyncAbstractTest): + def test_single_file(self): + sends = {'method': 'post', 'file': files[0], **checks} + self.send_return(sends, self.solver.rotate, files=files[0]) + + def test_file_param(self): + sends = {'method': 'post', + 'files': {'file_1': files[0]}, + **checks} + + self.send_return(sends, self.solver.rotate, files=files[:1]) + + def test_files_list(self): + sends = {'method': 'post', 'files': files_dict, **checks} + self.send_return(sends, self.solver.rotate, files=files) + + def test_files_dict(self): + sends = {'method': 'post', 'files': files_dict, **checks} + self.send_return(sends, self.solver.rotate, files=files_dict) + + def test_all_params(self): + params = { + 'angle': 40, + 'lang': 'en', + 'hintImg': hint_img, + 'hintText': hint_text + } + + sends = { + 'method': 'rotatecaptcha', + 'angle': 40, + 'lang': 'en', + 'textinstructions': hint_text, + 'files': {'file': files[0], 'imginstructions': hint_img}, + **checks + } + + self.send_return(sends, self.solver.rotate, file=files[0], **params) + + def test_not_found(self): + self.invalid_file(self.solver.rotate) + + def test_too_many(self): + self.too_many_files(self.solver.rotate) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_tencent.py b/tests/async/test_async_tencent.py new file mode 100644 index 0000000..7bacdc6 --- /dev/null +++ b/tests/async/test_async_tencent.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncTencentTest(AsyncAbstractTest): + def test_all_params(self): + params = { + "app_id": "197322596", + "url": "https://www.holla.world/random-video-chat#app" + } + + sends = { + "method": "tencent", + "app_id": "197322596", + "pageurl": "https://www.holla.world/random-video-chat#app", + } + + self.send_return(sends, self.solver.tencent, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_text.py b/tests/async/test_async_text.py new file mode 100644 index 0000000..aaea03b --- /dev/null +++ b/tests/async/test_async_text.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncTextTest(AsyncAbstractTest): + def test_only_text(self): + sends = { + 'method': 'post', + 'textcaptcha': 'Today is monday?', + } + + self.send_return(sends, + self.solver.text, + text='Today is monday?') + + def test_all_params(self): + params = { + 'text': 'Today is monday?', + 'lang': 'en', + } + + sends = { + 'method': 'post', + 'textcaptcha': 'Today is monday?', + 'lang': 'en', + } + + self.send_return(sends, self.solver.text, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_turnstile.py b/tests/async/test_async_turnstile.py new file mode 100644 index 0000000..fb26de9 --- /dev/null +++ b/tests/async/test_async_turnstile.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncTurnstileTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'sitekey': '0x4AAAAAAAC3DHQFLr1GavRN', + 'url': 'https://www.site.com/page/', + 'action': 'foo', + 'data': 'bar' + } + + sends = { + 'method': 'turnstile', + 'sitekey': '0x4AAAAAAAC3DHQFLr1GavRN', + 'action': 'foo', + 'data': 'bar', + 'pageurl': 'https://www.site.com/page/', + } + + self.send_return(sends, self.solver.turnstile, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/async/test_async_yandex_smart_captcha.py b/tests/async/test_async_yandex_smart_captcha.py new file mode 100644 index 0000000..cef17d5 --- /dev/null +++ b/tests/async/test_async_yandex_smart_captcha.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import unittest + +try: + from .abstract_async import AsyncAbstractTest +except ImportError: + from abstract_async import AsyncAbstractTest + + +class AsyncYandexSmartCaptchaTest(AsyncAbstractTest): + def test_all_params(self): + params = { + 'sitekey': 'FEXfAbHQsToo97VidNVk3j4dC74nGW1DgdPpL4O', + 'url': 'https://www.site.com/page/', + } + + sends = { + 'method': 'yandex', + 'sitekey': 'FEXfAbHQsToo97VidNVk3j4dC74nGW1DgdPpL4O', + 'pageurl': 'https://www.site.com/page/', + } + + self.send_return(sends, self.solver.yandex_smart, **params) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/abstract.py b/tests/sync/abstract.py old mode 100755 new mode 100644 similarity index 100% rename from tests/abstract.py rename to tests/sync/abstract.py diff --git a/tests/canvas_test.py b/tests/sync/canvas_test.py old mode 100755 new mode 100644 similarity index 86% rename from tests/canvas_test.py rename to tests/sync/canvas_test.py index 6a4f41d..974ff81 --- a/tests/canvas_test.py +++ b/tests/sync/canvas_test.py @@ -2,11 +2,20 @@ import unittest -from abstract import AbstractTest -file = '../examples/images/canvas.jpg' + +file = '../../examples/images/canvas.jpg' +hint_img = '../../examples/images/canvas_hint.jpg' hint = 'Draw around apple' +try: + from .abstract import AbstractTest + + file = file[3:] + hint_img = hint_img[3:] +except ImportError: + from abstract import AbstractTest + checks = {'canvas': 1, 'recaptcha': 1, 'textinstructions': hint} @@ -34,9 +43,6 @@ def test_base64_param(self): hintText=hint) def test_all_params(self): - - hint_img = '../examples/images/canvas_hint.jpg' - params = { 'previousId': 0, 'canSkip': 0, diff --git a/tests/test_amazon_waf.py b/tests/sync/test_amazon_waf.py old mode 100755 new mode 100644 similarity index 100% rename from tests/test_amazon_waf.py rename to tests/sync/test_amazon_waf.py diff --git a/tests/test_atb_captcha.py b/tests/sync/test_atb_captcha.py similarity index 100% rename from tests/test_atb_captcha.py rename to tests/sync/test_atb_captcha.py diff --git a/tests/test_canvas.py b/tests/sync/test_canvas.py old mode 100755 new mode 100644 similarity index 99% rename from tests/test_canvas.py rename to tests/sync/test_canvas.py index 5697cc1..a586215 --- a/tests/test_canvas.py +++ b/tests/sync/test_canvas.py @@ -13,12 +13,11 @@ try: from .abstract import AbstractTest - file = file[3:] - hint_img = hint_img[3:] - except ImportError: from abstract import AbstractTest + file = file[3:] + hint_img = hint_img[3:] diff --git a/tests/test_capy.py b/tests/sync/test_capy.py old mode 100755 new mode 100644 similarity index 100% rename from tests/test_capy.py rename to tests/sync/test_capy.py diff --git a/tests/test_coordinates.py b/tests/sync/test_coordinates.py old mode 100755 new mode 100644 similarity index 99% rename from tests/test_coordinates.py rename to tests/sync/test_coordinates.py index c09357e..25c2b4f --- a/tests/test_coordinates.py +++ b/tests/sync/test_coordinates.py @@ -12,13 +12,11 @@ try: from .abstract import AbstractTest - file = file[3:] - hint_img = hint_img[3:] - except ImportError: from abstract import AbstractTest - + file = file[3:] + hint_img = hint_img[3:] diff --git a/tests/test_cutcaptcha.py b/tests/sync/test_cutcaptcha.py similarity index 100% rename from tests/test_cutcaptcha.py rename to tests/sync/test_cutcaptcha.py diff --git a/tests/test_cybersiara.py b/tests/sync/test_cybersiara.py similarity index 100% rename from tests/test_cybersiara.py rename to tests/sync/test_cybersiara.py diff --git a/tests/test_datadome.py b/tests/sync/test_datadome.py similarity index 100% rename from tests/test_datadome.py rename to tests/sync/test_datadome.py diff --git a/tests/test_friendly_captcha.py b/tests/sync/test_friendly_captcha.py similarity index 100% rename from tests/test_friendly_captcha.py rename to tests/sync/test_friendly_captcha.py diff --git a/tests/test_funcaptcha.py b/tests/sync/test_funcaptcha.py old mode 100755 new mode 100644 similarity index 100% rename from tests/test_funcaptcha.py rename to tests/sync/test_funcaptcha.py diff --git a/tests/test_geetest.py b/tests/sync/test_geetest.py old mode 100755 new mode 100644 similarity index 100% rename from tests/test_geetest.py rename to tests/sync/test_geetest.py diff --git a/tests/test_geetest_v4.py b/tests/sync/test_geetest_v4.py old mode 100755 new mode 100644 similarity index 100% rename from tests/test_geetest_v4.py rename to tests/sync/test_geetest_v4.py diff --git a/tests/test_grid.py b/tests/sync/test_grid.py old mode 100755 new mode 100644 similarity index 99% rename from tests/test_grid.py rename to tests/sync/test_grid.py index 1c7d80f..84792f2 --- a/tests/test_grid.py +++ b/tests/sync/test_grid.py @@ -11,13 +11,11 @@ try: from .abstract import AbstractTest - file = file[3:] - hint_img = hint_img[3:] - except ImportError: from abstract import AbstractTest - + file = file[3:] + hint_img = hint_img[3:] diff --git a/tests/test_hcaptcha.py b/tests/sync/test_hcaptcha.py old mode 100755 new mode 100644 similarity index 100% rename from tests/test_hcaptcha.py rename to tests/sync/test_hcaptcha.py diff --git a/tests/test_keycaptcha.py b/tests/sync/test_keycaptcha.py old mode 100755 new mode 100644 similarity index 100% rename from tests/test_keycaptcha.py rename to tests/sync/test_keycaptcha.py diff --git a/tests/test_lemin.py b/tests/sync/test_lemin.py old mode 100755 new mode 100644 similarity index 100% rename from tests/test_lemin.py rename to tests/sync/test_lemin.py diff --git a/tests/test_mtcaptcha.py b/tests/sync/test_mtcaptcha.py similarity index 100% rename from tests/test_mtcaptcha.py rename to tests/sync/test_mtcaptcha.py diff --git a/tests/test_normal.py b/tests/sync/test_normal.py similarity index 99% rename from tests/test_normal.py rename to tests/sync/test_normal.py index 22f3688..16a717a 100644 --- a/tests/test_normal.py +++ b/tests/sync/test_normal.py @@ -9,12 +9,11 @@ try: from .abstract import AbstractTest - file = file[3:] - hint_img = hint_img[3:] - except ImportError: from abstract import AbstractTest + file = file[3:] + hint_img = hint_img[3:] diff --git a/tests/test_recaptcha.py b/tests/sync/test_recaptcha.py old mode 100755 new mode 100644 similarity index 100% rename from tests/test_recaptcha.py rename to tests/sync/test_recaptcha.py diff --git a/tests/test_rotate.py b/tests/sync/test_rotate.py old mode 100755 new mode 100644 similarity index 100% rename from tests/test_rotate.py rename to tests/sync/test_rotate.py index 893e2b7..2e2afb1 --- a/tests/test_rotate.py +++ b/tests/sync/test_rotate.py @@ -12,13 +12,13 @@ try: from .abstract import AbstractTest - files = [f[3:] for f in files] - hint_img = hint_img[3:] - except ImportError: from abstract import AbstractTest + files = [f[3:] for f in files] + hint_img = hint_img[3:] + diff --git a/tests/test_tencent.py b/tests/sync/test_tencent.py similarity index 100% rename from tests/test_tencent.py rename to tests/sync/test_tencent.py diff --git a/tests/test_text.py b/tests/sync/test_text.py old mode 100755 new mode 100644 similarity index 100% rename from tests/test_text.py rename to tests/sync/test_text.py diff --git a/tests/test_turnstile.py b/tests/sync/test_turnstile.py old mode 100755 new mode 100644 similarity index 100% rename from tests/test_turnstile.py rename to tests/sync/test_turnstile.py diff --git a/tests/test_yandex_smart_captcha.py b/tests/sync/test_yandex_smart_captcha.py similarity index 100% rename from tests/test_yandex_smart_captcha.py rename to tests/sync/test_yandex_smart_captcha.py diff --git a/twocaptcha/__init__.py b/twocaptcha/__init__.py index 825c9dc..7d78f53 100644 --- a/twocaptcha/__init__.py +++ b/twocaptcha/__init__.py @@ -1,6 +1,11 @@ from .api import ApiClient -from .solver import (TwoCaptcha, SolverExceptions, ValidationException, - NetworkException, ApiException, TimeoutException) +from .solver import TwoCaptcha + +from .async_api import AsyncApiClient +from .async_solver import AsyncTwoCaptcha + +from .solver import SolverExceptions, ValidationException, NetworkException, ApiException, TimeoutException + """ Python 3 package for easy integration with the API of 2captcha captcha solving service to bypass recaptcha, diff --git a/twocaptcha/api.py b/twocaptcha/api.py index 147a8ed..38a54ac 100644 --- a/twocaptcha/api.py +++ b/twocaptcha/api.py @@ -2,20 +2,16 @@ import requests - -class NetworkException(Exception): - pass - - -class ApiException(Exception): - pass +try: + from .exceptions.api import NetworkException, ApiException +except ImportError: + from twocaptcha.exceptions.api import NetworkException, ApiException class ApiClient(): - def __init__(self, post_url = '2captcha.com'): + def __init__(self, post_url='2captcha.com'): self.post_url = post_url - - + def in_(self, files={}, **kwargs): ''' @@ -43,7 +39,7 @@ def in_(self, files={}, **kwargs): ''' try: - current_url = 'https://'+self.post_url+'/in.php' + current_url = 'https://' + self.post_url + '/in.php' if files: files = {key: open(path, 'rb') for key, path in files.items()} @@ -101,7 +97,7 @@ def res(self, **kwargs): ''' try: - current_url_out = 'https://'+self.post_url+'/res.php' + current_url_out = 'https://' + self.post_url + '/res.php' resp = requests.get(current_url_out, params=kwargs) if resp.status_code != 200: diff --git a/twocaptcha/async_api.py b/twocaptcha/async_api.py new file mode 100644 index 0000000..f7a407c --- /dev/null +++ b/twocaptcha/async_api.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 + +from contextlib import AsyncExitStack + +import aiofiles +import httpx + +try: + from .exceptions.api import NetworkException, ApiException +except ImportError: + from twocaptcha.exceptions.api import NetworkException, ApiException + + +class AsyncApiClient(): + def __init__(self, post_url='2captcha.com'): + self.post_url = post_url + + async def in_(self, files={}, **kwargs): + ''' + + sends POST-request (files and/or params) to solve captcha + + Parameters + ---------- + files : TYPE, optional + DESCRIPTION. The default is {}. + **kwargs : TYPE + DESCRIPTION. + + Raises + ------ + NetworkException + DESCRIPTION. + ApiException + DESCRIPTION. + + Returns + ------- + resp : TYPE + DESCRIPTION. + + ''' + + try: + current_url = 'https://' + self.post_url + '/in.php' + + async with httpx.AsyncClient() as client: + if files: + async with AsyncExitStack() as stack: + file_objects = {} + for key, path in files.items(): + file_handle = await stack.enter_async_context(aiofiles.open(path, 'rb')) + content = await file_handle.read() + file_objects[key] = content + + resp = await client.post(current_url, + data=kwargs, + files=file_objects) + + elif 'file' in kwargs: + file_path = kwargs.pop('file') + async with aiofiles.open(file_path, 'rb') as file_handle: + content = await file_handle.read() + resp = await client.post(current_url, + data=kwargs, + files={'file': content}) + else: + resp = await client.post(current_url, + data=kwargs) + + except httpx.RequestError as e: + raise NetworkException(e) + + if resp.status_code != 200: + raise NetworkException(f'bad response: {resp.status_code}') + + resp = resp.content.decode('utf-8') + + if 'ERROR' in resp: + raise ApiException(resp) + + return resp + + async def res(self, **kwargs): + ''' + sends additional GET-requests (solved captcha, balance, report etc.) + + Parameters + ---------- + **kwargs : TYPE + DESCRIPTION. + + Raises + ------ + NetworkException + DESCRIPTION. + ApiException + DESCRIPTION. + + Returns + ------- + resp : TYPE + DESCRIPTION. + + ''' + + try: + current_url_out = 'https://' + self.post_url + '/res.php' + + async with httpx.AsyncClient() as client: + resp = await client.get(current_url_out, params=kwargs) + + if resp.status_code != 200: + raise NetworkException(f'bad response: {resp.status_code}') + + resp = resp.content.decode('utf-8') + + if 'ERROR' in resp: + raise ApiException(resp) + + except httpx.RequestError as e: + raise NetworkException(e) + + return resp diff --git a/twocaptcha/async_solver.py b/twocaptcha/async_solver.py new file mode 100644 index 0000000..6fb78c7 --- /dev/null +++ b/twocaptcha/async_solver.py @@ -0,0 +1,1120 @@ +#!/usr/bin/env python3 + +import asyncio +import os +import sys +import time +from base64 import b64encode + +import aiofiles +import httpx + +try: + from .async_api import AsyncApiClient + from .exceptions.solver import ValidationException, NetworkException, TimeoutException, ApiException, \ + SolverExceptions +except ImportError: + from async_api import AsyncApiClient + from twocaptcha.exceptions.solver import ValidationException, NetworkException, TimeoutException, ApiException, \ + SolverExceptions + + +class AsyncTwoCaptcha(): + def __init__(self, + apiKey, + softId=4580, + callback=None, + defaultTimeout=120, + recaptchaTimeout=600, + pollingInterval=10, + server='2captcha.com', + extendedResponse=None): + + self.API_KEY = apiKey + self.soft_id = softId + self.callback = callback + self.default_timeout = defaultTimeout + self.recaptcha_timeout = recaptchaTimeout + self.polling_interval = pollingInterval + self.api_client = AsyncApiClient(post_url=str(server)) + self.max_files = 9 + self.exceptions = SolverExceptions + self.extendedResponse = extendedResponse + + async def normal(self, file, **kwargs): + '''Wrapper for solving a normal captcha (image). + + Parameters + __________ + file : file + Captcha image file. * required if you submit image as a file (method=post). + body : str + Base64-encoded captcha image. * required if you submit image as Base64-encoded string (method=base64). + phrase : int, optional + 0 - captcha contains one word. 1 - captcha contains two or more words. + Default: 0. + numeric : int, optional + 0 - not specified. 1 - captcha contains only numbers. 2 - captcha contains only letters. 3 - captcha + contains only numbers OR only letters. 4 - captcha MUST contain both numbers AND letters. + Default: 0 + minLen : int, optional + 0 - not specified. 1..20 - minimal number of symbols in captcha. + Default: 0. + maxLen : int, optional + 0 - not specified. 1..20 - maximal number of symbols in captcha. + Default: 0. + caseSensitive : int, optional + 0 - captcha in not case sensitive. 1 - captcha is case sensitive. + Default: 0. + calc : int, optional + 0 - not specified. 1 - captcha requires calculation (e.g. type the result 4 + 8 = ). + Default: 0. + lang : str, optional + Language code. See the list of supported languages https://2captcha.com/2captcha-api#language. + hintText : str, optional + Max 140 characters. Endcoding: UTF-8. Text will be shown to worker to help him to solve the captcha correctly. + For example: type red symbols only. + hintImg : img, optional + Max 400x150px, 100 kB. Image with instruction for solving reCAPTCHA. Not required if you're sending + instruction as text with textinstructions. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + ''' + + method = await self.get_method(file) + result = await self.solve(**method, **kwargs) + return result + + async def audio(self, file, lang, **kwargs): + '''Wrapper for solving audio captcha. + + Parameters + __________ + body : str + Base64 encoded audio file in mp3 format. Max file size: 1 MB. + lang : str + The language of audio record. Supported languages are: "en", "ru", "de", "el", "pt", "fr". + ''' + + method = "audio" + + if not file: + raise ValidationException('File is none') + elif not '.' in file and len(file) > 50: + body = file + elif file.endswith(".mp3") and file.startswith("http"): + async with httpx.AsyncClient() as client: + response = await client.get(file) + if response.status_code != 200: + raise ValidationException(f'File could not be downloaded from url: {file}') + body = b64encode(response.content).decode('utf-8') + elif file.endswith(".mp3"): + async with aiofiles.open(file, "rb") as media: + file_content = await media.read() + body = b64encode(file_content).decode('utf-8') + else: + raise ValidationException('File extension is not .mp3 or it is not a base64 string.') + + if not lang or lang not in ("en", "ru", "de", "el", "pt", "fr"): + raise ValidationException(f'Lang not in "en", "ru", "de", "el", "pt", "fr". You send {lang}') + + result = await self.solve(body=body, method=method, **kwargs) + return result + + async def text(self, text, **kwargs): + '''Wrapper for solving text captcha. + + Parameters + __________ + text : str + Max 140 characters. Endcoding: UTF-8. Text will be shown to worker to help him to solve the captcha correctly. + For example: type red symbols only. + lang: str, optional + Language code. See the list of supported languages https://2captcha.com/2captcha-api#language. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + ''' + + result = await self.solve(text=text, method='post', **kwargs) + return result + + async def recaptcha(self, sitekey, url, version='v2', enterprise=0, **kwargs): + '''Wrapper for solving recaptcha (v2, v3). + + Parameters + _______________ + sitekey : str + Value of sitekey parameter you found on page. + url : str + Full URL of the page where you see the reCAPTCHA. + domain : str, optional + Domain used to load the captcha: google.com or recaptcha.net. Default: google.com. + invisible : int, optional + 1 - means that reCAPTCHA is invisible. 0 - normal reCAPTCHA. Default: 0. + version : str, optional + v3 — defines that you're sending a reCAPTCHA V3. Default: v2. + enterprise : str, optional + 1 - defines that you're sending reCAPTCHA Enterpise. Default: 0. + action : str, optional + Value of action parameter you found on page. Default: verify. + score : str, only for v3, optional + The score needed for resolution. Currently, it's almost impossible to get token with score higher than 0.3. + Default: 0.4. + data-s : str, only for v2, optional + Value of data-s parameter you found on page. Curenttly applicable for Google Search and other Google services. + cookies : str, only for v2, optional + Your cookies that will be passed to our worker who solve the captha. We also return worker's cookies in the + response if you use json=1. Format: KEY:Value, separator: semicolon, example: KEY1:Value1;KEY2:Value2; + userAgent : str, only for v2, optional + Your userAgent that will be passed to our worker and used to solve the captcha. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + params = { + 'googlekey': sitekey, + 'url': url, + 'method': 'userrecaptcha', + 'version': version, + 'enterprise': enterprise, + **kwargs, + } + + result = await self.solve(timeout=self.recaptcha_timeout, **params) + return result + + async def funcaptcha(self, sitekey, url, **kwargs): + '''Wrapper for solving funcaptcha. + + Parameters + __________ + sitekey : str + Value of pk or data-pkey parameter you found on page. + url : str + Full URL of the page where you see the FunCaptcha. + surl : str, optional + Value of surl parameter you found on page. + userAgent: str, optional + Tells us to use your user-agent value. + data[key] : str, optional + Custom data to pass to FunCaptcha. For example: data[blob]=stringValue. + softId : str, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + result = await self.solve(publickey=sitekey, + url=url, + method='funcaptcha', + **kwargs) + return result + + async def geetest(self, gt, challenge, url, **kwargs): + '''Wrapper for solving geetest captcha. + + Parameters: + __________ + gt : str + Value of gt parameter you found on target website. + challenge : str + Value of challenge parameter you found on target website. + url : str + Full URL of the page where you see Geetest captcha. + offline : num, optional + In rare cases initGeetest can be called with offline parameter. If the call uses offline: true, set the + value to 1. Default: 0. + new_captcha : num, optional + In rare cases initGeetest can be called with new_captcha parameter. If the call uses new_captcha: true, set + the value to 1. Mostly used with offline parameter. + userAgent : str, optional + Your userAgent that will be passed to our worker and used to solve the captcha. + apiServer : str, optional + Value of api_server parameter you found on target website. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + result = await self.solve(gt=gt, + challenge=challenge, + url=url, + method='geetest', + **kwargs) + return result + + async def hcaptcha(self, sitekey, url, **kwargs): + '''Wrapper for solving hcaptcha. + + Parameters + __________ + sitekey : str + Value of data-sitekey parameter you found on page. + url : str + Full URL of the page where you bypass the captcha. + invisible : num, optional + Use 1 for invisible version of hcaptcha. Currently it is a very rare case. + Default: 0. + data : str, optional + Custom data that is used in some implementations of hCaptcha, mostly with invisible=1. In most cases you see + it as rqdata inside network requests. Format: "data": "rqDataValue". + domain : str, optional + Domain used to load the captcha: hcaptcha.com or js.hcaptcha.com. Default: hcaptcha.com. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + result = await self.solve(sitekey=sitekey, + url=url, + method='hcaptcha', + **kwargs) + return result + + async def keycaptcha(self, s_s_c_user_id, s_s_c_session_id, + s_s_c_web_server_sign, s_s_c_web_server_sign2, url, + **kwargs): + '''Wrapper for solving. + + Parameters + __________ + s_s_c_user_id : str + Value of s_s_c_user_id parameter you found on page. + s_s_c_session_id : str + Value of s_s_c_session_id parameter you found on page. + s_s_c_web_server_sign : str + Value of s_s_c_web_server_sign parameter you found on page. + s_s_c_web_server_sign2 : str + Value of s_s_c_web_server_sign2 parameter you found on page. + url : str + Full URL of the page where you see the KeyCaptcha. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + params = { + 's_s_c_user_id': s_s_c_user_id, + 's_s_c_session_id': s_s_c_session_id, + 's_s_c_web_server_sign': s_s_c_web_server_sign, + 's_s_c_web_server_sign2': s_s_c_web_server_sign2, + 'url': url, + 'method': 'keycaptcha', + **kwargs, + } + + result = await self.solve(**params) + return result + + async def capy(self, sitekey, url, **kwargs): + '''Wrapper for solving capy. + + Parameters + __________ + sitekey : str + The domain part of script URL you found on page. Default value: https://jp.api.capy.me/. + url : str + Full URL of the page where you see the captcha. + api_server : str, optional + The domain part of script URL you found on page. Default value: https://jp.api.capy.me/. + version : str, optional + The version of captcha task: "puzzle" (assemble a puzzle) or "avatar" (drag an object). Default: puzzle. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + result = await self.solve(captchakey=sitekey, + url=url, + method='capy', + **kwargs) + return result + + async def grid(self, file, **kwargs): + '''Wrapper for solving grid captcha (image). + + Required: + file : file + Captcha image file. * required if you submit image as a file (method=post). + body : str + Base64-encoded captcha image. * required if you submit image as Base64-encoded string (method=base64). + hintText : str + Max 140 characters. Endcoding: UTF-8. Text with instruction for solving reCAPTCHA. For example: select images + with trees. Not required if you're sending instruction as an image with imginstructions. + hintImg : img + Max 400x150px, 100 kB. Image with instruction for solving reCAPTCHA. Not required if you're sending + instruction as text with textinstructions. + rows : int, optional + Number of rows in reCAPTCHA grid. + cols : itn, optional + Number of columns in reCAPTCHA grid. + previousId : str, optional + Id of your previous request with the same captcha challenge. + canSkip : int, optional + 0 - not specified. 1 - possibly there's no images that fit the instruction. Set the value to 1 only if it's + possible that there's no images matching to the instruction. We'll provide a button "No matching images" to + worker, and you will receive No_matching_images as answer. + Default: 0. + lang: str, optional + Language code. See the list of supported languages https://2captcha.com/2captcha-api#language. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + method = await self.get_method(file) + + params = { + 'recaptcha': 1, + **method, + **kwargs, + } + + result = await self.solve(**params) + return result + + async def canvas(self, file, **kwargs): + '''Wrapper for solving canvas captcha (image). + + Parameters + __________ + file : file + Captcha image file. * required if you submit image as a file (method=post). + body : str + Base64-encoded captcha image. * required if you submit image as Base64-encoded string (method=base64). + hintText : str + Max 140 characters. Endcoding: UTF-8. Text with instruction for solving reCAPTCHA. For example: select + images with trees. Not required if you're sending instruction as an image with imginstructions. + hintImg : img + Max 400x150px, 100 kB. Image with instruction for solving reCAPTCHA. Not required if you're sending + instruction as text with textinstructions. + canSkip : int, optional + 0 - not specified. 1 - possibly there's no images that fit the instruction. Set the value to 1 only if it's + possible that there's no images matching to the instruction. We'll provide a button "No matching images" to + worker, and you will receive No_matching_images as answer. + Default: 0. + lang : int, optional + 0 - not specified. 1 - Cyrillic captcha. 2 - Latin captcha. + Default: 0. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + ''' + + if not ('hintText' in kwargs or 'hintImg' in kwargs): + raise ValidationException( + 'parameters required: hintText and/or hintImg') + + method = await self.get_method(file) + + params = { + 'recaptcha': 1, + 'canvas': 1, + **method, + **kwargs, + } + + result = await self.solve(**params) + return result + + async def coordinates(self, file, **kwargs): + '''Wrapper for solving coordinates captcha (image). + + Parameters + __________ + file : file + Captcha image file. * required if you submit image as a file (method=post). + body : str + Base64-encoded captcha image. * required if you submit image as Base64-encoded string (method=base64). + hintText : str + Max 140 characters. Endcoding: UTF-8. Text with instruction for solving the captcha. For example: click on + images with ghosts. Not required if the image already contains the instruction. + hintImg : img + Max 400x150px, 100 kB. Image with instruction for solving reCAPTCHA. Not required if you're sending + instruction as text with textinstructions. + lang : str, optional + Language code. See the list of supported languages https://2captcha.com/2captcha-api#language. + min_clicks : int, optional + The minimum number of clicks that need to be done. + max_clicks : int, optional + The maximum number of clicks that can be done. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + ''' + + method = await self.get_method(file) + + params = { + 'coordinatescaptcha': 1, + **method, + **kwargs, + } + + result = await self.solve(**params) + return result + + async def rotate(self, files, **kwargs): + '''Wrapper for solving rotate captcha (image). + + Parameters + __________ + files : file + Captcha image file. * required if you submit image as a file (method=post). + body : str + Base64-encoded captcha image. * required if you submit image as Base64-encoded string (method=base64). + angle : int, optional + Angle for one rotation step in degrees. If not defined we'll use the default value for FunCaptcha: 40 degrees. + Default: 40. + lang : str, optional + Language code. See the list of supported languages https://2captcha.com/2captcha-api#language. + hintImg : str, optional + Image with instruction for worker to help him to solve captcha correctly. + hintText : str, optional + Text will be shown to worker to help him to to solve captcha correctly. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + if isinstance(files, str): + file = await self.get_method(files) + file = file.get('file') + + result = await self.solve(file=file, method='rotatecaptcha', **kwargs) + return result + + elif isinstance(files, dict): + files = list(files.values()) + + files = self.extract_files(files) + + result = await self.solve(files=files, method='rotatecaptcha', **kwargs) + return result + + async def geetest_v4(self, captcha_id, url, **kwargs): + '''Wrapper for solving geetest_v4 captcha. + + Parameters + __________ + captcha_id : str + Value of captcha_id parameter you found on target website. + url: str + Full URL of the page where you see Geetest captcha. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + result = await self.solve(captcha_id=captcha_id, + url=url, + method='geetest_v4', + **kwargs) + return result + + async def lemin(self, captcha_id, div_id, url, **kwargs): + '''Wrapper for solving Lemin Cropped Captcha. + + Parameters + __________ + captcha_id : str + Value of captcha_id parameter you found on page. + div_id : str + The id of captcha parent div element. + url : str + Full URL of the page where you see the captcha. + api_server : str, optional + The domain part of script URL you found on page. Default value: https://api.leminnow.com/. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + result = await self.solve(captcha_id=captcha_id, + div_id=div_id, + url=url, + method='lemin', + **kwargs) + return result + + async def atb_captcha(self, app_id, api_server, url, **kwargs): + '''Wrapper for solving atbCAPTCHA. + + Parameters + __________ + app_id : str + The value of appId parameter in the website source code. + api_server : str + The value of apiServer parameter in the website source code. + url : str + The full URL of target web page where the captcha is loaded. We do not open the page, not a problem if it is + available only for authenticated users. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + + ''' + + result = await self.solve(app_id=app_id, + api_server=api_server, + url=url, + method='atb_captcha', + **kwargs) + return result + + async def turnstile(self, sitekey, url, **kwargs): + '''Wrapper for solving Cloudflare Turnstile. + + Parameters + __________ + sitekey : str + Value of sitekey parameter you found on page. + url : str + Full URL of the page where you see the captcha. + useragent : str + User-Agent of your browser. Must match the User-Agent you use to access the site. + Use only modern browsers released within the last 6 months. + action : str. optional + Value of optional action parameter you found on page, can be defined in data-action attribute or passed + to turnstile.render call. + data : str, optional + The value of cData passed to turnstile.render call. Also can be defined in data-cdata attribute. + pagedata : str, optional + The value of the chlPageData parameter when calling turnstile.render. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + result = await self.solve(sitekey=sitekey, + url=url, + method='turnstile', + **kwargs) + return result + + async def amazon_waf(self, sitekey, iv, context, url, **kwargs): + '''Wrapper for solving Amazon WAF. + + Parameters + __________ + sitekey : str + Value of key parameter you found on the page. + iv : str + Value of iv parameter you found on the page. + context : str + Value of optional context parameter you found on page. + url : str + Full URL of the page where you see the captcha. + challenge_script : str, optional + The source URL of challenge.js script on the page. + captcha_script : str, optional + The source URL of captcha.js script on the page. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + result = await self.solve(sitekey=sitekey, + iv=iv, + context=context, + url=url, + method='amazon_waf', + **kwargs) + + return result + + async def mtcaptcha(self, sitekey, url, **kwargs): + '''Wrapper for solving MTCaptcha. + + Parameters + __________ + sitekey : str + The value of sitekey parameter found on the page. + url : str + Full URL of the page where you solve the captcha. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + result = await self.solve(sitekey=sitekey, + url=url, + method='mt_captcha', + **kwargs) + return result + + async def friendly_captcha(self, sitekey, url, **kwargs): + '''Wrapper for solving Friendly Captcha. + + Parameters + __________ + sitekey : str + The value of data-sitekey attribute of captcha's div element on page. + url : str + Full URL of the page where you solve the captcha. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + result = await self.solve(sitekey=sitekey, + url=url, + method='friendly_captcha', + **kwargs) + return result + + async def tencent(self, app_id, url, **kwargs): + '''Wrapper for solving Tencent captcha. + + Parameters + __________ + app_id : str + The value of appId parameter in the website source code. + url : str + The full URL of target web page where the captcha is loaded. We do not open the page, not a problem if it is + available only for authenticated users. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + result = await self.solve(app_id=app_id, + url=url, + method="tencent", + **kwargs) + return result + + async def cutcaptcha(self, misery_key, apikey, url, **kwargs): + '''Wrapper for solving Friendly Captcha. + + Parameters + __________ + misery_key : str + The value of CUTCAPTCHA_MISERY_KEY variable defined on page. + apikey : str + The value of data-apikey attribute of iframe's body. Also, the name of javascript file included on the page. + url : str + Full URL of the page where you solve the captcha. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + + result = await self.solve(misery_key=misery_key, + api_key=apikey, + url=url, + method='cutcaptcha', + **kwargs) + return result + + async def datadome(self, captcha_url, pageurl, userAgent, proxy, **kwargs): + """Wrapper for solving DataDome Captcha. + + Parameters + __________ + captcha_url: str + The value of the 'src' parameter for the 'iframe' element containing the captcha on the page. + pageurl: str + Full URL of the page that triggers the captcha when you go to it. + userAgent: str + User-Agent of the browser that will be used by the employee when loading the captcha. + proxy : dict + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + """ + + result = await self.solve(method='datadome', + captcha_url=captcha_url, + pageurl=pageurl, + userAgent=userAgent, + proxy=proxy, + **kwargs) + return result + + async def cybersiara(self, master_url_id, pageurl, userAgent, **kwargs): + '''Wrapper for solving CyberSiARA captcha. + + Parameters + __________ + master_url_id : str + The value of the MasterUrlId parameter from the request to API/CyberSiara/GetCyberSiara. + pageurl : str + Full URL of the page with captcha. + userAgent : str + User-Agent of your browser. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + ''' + result = await self.solve(method='cybersiara', + master_url_id=master_url_id, + pageurl=pageurl, + userAgent=userAgent, + **kwargs) + return result + + async def yandex_smart(self, sitekey, url, **kwargs): + '''Wrapper for solving Yandex Smart. + + Parameters + __________ + sitekey : str + The value of data-sitekey attribute of captcha's div element on page. + url : str + Full URL of the page where you solve the captcha. + softId : int, optional + ID of software developer. Developers who integrated their software with 2Captcha get reward: 10% of + spendings of their software users. + callback : str, optional + URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on + the server. More info here https://2captcha.com/2captcha-api#pingback. + proxy : dict, optional + {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}. + userAgent: str, optional + User-Agent of the browser that will be used by the employee when loading the captcha. + ''' + + result = await self.solve(sitekey=sitekey, + url=url, + method='yandex', + **kwargs) + return result + + async def solve(self, timeout=0, polling_interval=0, **kwargs): + '''Sends captcha, receives result. + + Parameters + __________ + timeout : float + + polling_interval : int + + **kwargs : dict + all captcha params + + Returns + + result : string + ''' + + id_ = await self.send(**kwargs) + result = {'captchaId': id_} + + if self.callback is None: + timeout = float(timeout or self.default_timeout) + sleep = int(polling_interval or self.polling_interval) + + code = await self.wait_result(id_, timeout, sleep) + + if self.extendedResponse == True: + new_code = { + key if key != 'request' else 'code': value + for key, value in code.items() + if key != 'status' + } + result.update(new_code) + else: + result.update({'code': code}) + + return result + + async def wait_result(self, id_, timeout, polling_interval): + max_wait = time.time() + timeout + + while time.time() < max_wait: + try: + return await self.get_result(id_) + except NetworkException: + await asyncio.sleep(polling_interval) + + raise TimeoutException(f'timeout {timeout} exceeded') + + async def get_method(self, file): + if not file: + raise ValidationException('File required') + + if not '.' in file and len(file) > 50: + return {'method': 'base64', 'body': file} + + if file.startswith('http'): + async with httpx.AsyncClient() as client: + img_resp = await client.get(file) + if img_resp.status_code != 200: + raise ValidationException(f'File could not be downloaded from url: {file}') + return {'method': 'base64', 'body': b64encode(img_resp.content).decode('utf-8')} + + if not os.path.exists(file): + raise ValidationException(f'File not found: {file}') + + return {'method': 'post', 'file': file} + + async def send(self, **kwargs): + """This method can be used for manual captcha submission + + Parameters + _________ + method : str + The name of the method must be found in the documentation https://2captcha.com/2captcha-api + kwargs: dict + All captcha params + Returns + + """ + params = self.default_params(kwargs) + params = self.rename_params(params) + + params, files = self.check_hint_img(params) + + response = await self.api_client.in_(files=files, **params) + + if not response.startswith('OK|'): + raise ApiException(f'cannot recognize response {response}') + + return response[3:] + + async def get_result(self, id_): + import json + """This method can be used for manual captcha answer polling. + + Parameters + __________ + id_ : str + ID of the captcha sent for solution + Returns + + answer : text + """ + if self.extendedResponse == True: + response = await self.api_client.res(key=self.API_KEY, action='get', id=id_, json=1) + response_data = json.loads(response) + + if response_data.get("status") == 0: + raise NetworkException + + if not response_data.get("status") == 1: + raise ApiException(f'Unexpected status in response: {response_data}') + + return response_data + else: + response = await self.api_client.res(key=self.API_KEY, action='get', id=id_) + + if response == 'CAPCHA_NOT_READY': + raise NetworkException + + if not response.startswith('OK|'): + raise ApiException(f'cannot recognize response {response}') + + return response[3:] + + async def balance(self): + '''Get my balance + + Returns + + balance : float + ''' + response = await self.api_client.res(key=self.API_KEY, action='getbalance') + return float(response) + + async def report(self, id_, correct): + '''Report of solved captcha: good/bad. + + Parameters + __________ + id_ : str + captcha ID + + correct : bool + True/False + + Returns + None. + + ''' + rep = 'reportgood' if correct else 'reportbad' + await self.api_client.res(key=self.API_KEY, action=rep, id=id_) + return + + def rename_params(self, params): + replace = { + 'caseSensitive': 'regsense', + 'minLen': 'min_len', + 'maxLen': 'max_len', + 'minLength': 'min_len', + 'maxLength': 'max_len', + 'hintText': 'textinstructions', + 'hintImg': 'imginstructions', + 'url': 'pageurl', + 'score': 'min_score', + 'text': 'textcaptcha', + 'rows': 'recaptcharows', + 'cols': 'recaptchacols', + 'previousId': 'previousID', + 'canSkip': 'can_no_answer', + 'apiServer': 'api_server', + 'softId': 'soft_id', + 'callback': 'pingback', + 'datas': 'data-s', + } + + new_params = { + v: params.pop(k) + for k, v in replace.items() if k in params + } + + proxy = params.pop('proxy', '') + proxy and new_params.update({ + 'proxy': proxy['uri'], + 'proxytype': proxy['type'] + }) + + new_params.update(params) + + return new_params + + def default_params(self, params): + params.update({'key': self.API_KEY}) + + callback = params.pop('callback', self.callback) + soft_id = params.pop('softId', self.soft_id) + + if callback: params.update({'callback': callback}) + if soft_id: params.update({'softId': soft_id}) + + self.has_callback = bool(callback) + + return params + + def extract_files(self, files): + if len(files) > self.max_files: + raise ValidationException( + f'Too many files (max: {self.max_files})') + + not_exists = [f for f in files if not (os.path.exists(f))] + + if not_exists: + raise ValidationException(f'File not found: {not_exists}') + + files = {f'file_{e + 1}': f for e, f in enumerate(files)} + return files + + def check_hint_img(self, params): + hint = params.pop('imginstructions', None) + files = params.pop('files', {}) + + if not hint: + return params, files + + if not '.' in hint and len(hint) > 50: + params.update({'imginstructions': hint}) + return params, files + + if not os.path.exists(hint): + raise ValidationException(f'File not found: {hint}') + + if not files: + files = {'file': params.pop('file', {})} + + files.update({'imginstructions': hint}) + + return params, files + + +if __name__ == '__main__': + async def main(): + key = sys.argv[1] + sol = AsyncTwoCaptcha(key) + + + asyncio.run(main()) diff --git a/twocaptcha/exceptions/__init__.py b/twocaptcha/exceptions/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/twocaptcha/exceptions/api.py b/twocaptcha/exceptions/api.py new file mode 100644 index 0000000..93b76eb --- /dev/null +++ b/twocaptcha/exceptions/api.py @@ -0,0 +1,6 @@ +class NetworkException(Exception): + pass + + +class ApiException(Exception): + pass diff --git a/twocaptcha/exceptions/solver.py b/twocaptcha/exceptions/solver.py new file mode 100644 index 0000000..5d73043 --- /dev/null +++ b/twocaptcha/exceptions/solver.py @@ -0,0 +1,18 @@ +class SolverExceptions(Exception): + pass + + +class ValidationException(SolverExceptions): + pass + + +class NetworkException(SolverExceptions): + pass + + +class ApiException(SolverExceptions): + pass + + +class TimeoutException(SolverExceptions): + pass diff --git a/twocaptcha/solver.py b/twocaptcha/solver.py index b6f9f1c..95ee082 100755 --- a/twocaptcha/solver.py +++ b/twocaptcha/solver.py @@ -1,36 +1,20 @@ #!/usr/bin/env python3 -import os, sys +import os +import sys import time -import requests from base64 import b64encode +import requests try: from .api import ApiClient - + from .exceptions.solver import ValidationException, NetworkException, TimeoutException, ApiException, \ + SolverExceptions except ImportError: from api import ApiClient - - -class SolverExceptions(Exception): - pass - - -class ValidationException(SolverExceptions): - pass - - -class NetworkException(SolverExceptions): - pass - - -class ApiException(SolverExceptions): - pass - - -class TimeoutException(SolverExceptions): - pass + from twocaptcha.exceptions.solver import ValidationException, NetworkException, TimeoutException, ApiException, \ + SolverExceptions class TwoCaptcha(): @@ -41,7 +25,7 @@ def __init__(self, defaultTimeout=120, recaptchaTimeout=600, pollingInterval=10, - server = '2captcha.com', + server='2captcha.com', extendedResponse=None): self.API_KEY = apiKey @@ -50,7 +34,7 @@ def __init__(self, self.default_timeout = defaultTimeout self.recaptcha_timeout = recaptchaTimeout self.polling_interval = pollingInterval - self.api_client = ApiClient(post_url = str(server)) + self.api_client = ApiClient(post_url=str(server)) self.max_files = 9 self.exceptions = SolverExceptions self.extendedResponse = extendedResponse @@ -127,7 +111,7 @@ def audio(self, file, lang, **kwargs): body = b64encode(response.content).decode('utf-8') elif file.endswith(".mp3"): with open(file, "rb") as media: - body = b64encode(media.read()).decode('utf-8') + body = b64encode(media.read()).decode('utf-8') else: raise ValidationException('File extension is not .mp3 or it is not a base64 string.') @@ -557,7 +541,6 @@ def rotate(self, files, **kwargs): result = self.solve(files=files, method='rotatecaptcha', **kwargs) return result - def geetest_v4(self, captcha_id, url, **kwargs): '''Wrapper for solving geetest_v4 captcha. @@ -583,7 +566,6 @@ def geetest_v4(self, captcha_id, url, **kwargs): method='geetest_v4', **kwargs) return result - def lemin(self, captcha_id, div_id, url, **kwargs): '''Wrapper for solving Lemin Cropped Captcha. @@ -638,7 +620,6 @@ def atb_captcha(self, app_id, api_server, url, **kwargs): method='atb_captcha', **kwargs) return result - def turnstile(self, sitekey, url, **kwargs): '''Wrapper for solving Cloudflare Turnstile. @@ -674,7 +655,6 @@ def turnstile(self, sitekey, url, **kwargs): method='turnstile', **kwargs) return result - def amazon_waf(self, sitekey, iv, context, url, **kwargs): '''Wrapper for solving Amazon WAF. @@ -704,12 +684,12 @@ def amazon_waf(self, sitekey, iv, context, url, **kwargs): ''' result = self.solve(sitekey=sitekey, - iv=iv, + iv=iv, context=context, url=url, method='amazon_waf', **kwargs) - + return result def mtcaptcha(self, sitekey, url, **kwargs): @@ -838,7 +818,7 @@ def datadome(self, captcha_url, pageurl, userAgent, proxy, **kwargs): proxy=proxy, **kwargs) return result - + def cybersiara(self, master_url_id, pageurl, userAgent, **kwargs): '''Wrapper for solving CyberSiARA captcha. @@ -1119,7 +1099,7 @@ def extract_files(self, files): if not_exists: raise ValidationException(f'File not found: {not_exists}') - files = {f'file_{e+1}': f for e, f in enumerate(files)} + files = {f'file_{e + 1}': f for e, f in enumerate(files)} return files def check_hint_img(self, params): @@ -1146,6 +1126,5 @@ def check_hint_img(self, params): if __name__ == '__main__': - key = sys.argv[1] sol = TwoCaptcha(key)