ProxyStr
An analogue of better-proxy by alenkimov, but with string-like behavior, support for mobile proxies, and proxy checking functions. ProxyStr is heavier than better-proxy and requires httpx but if you need proxies, you will likely need this library anyway.
isinstance(Proxy('127.0.0.1:3001'), str) # --> True
pip install proxystr
Full list of depencies: pydantic, httpx, httpx-socks
Supports various proxy formats
from proxystr import Proxy
Proxy('host:port')
Proxy('host:port:login:password')
Proxy('login:password@host:port')
Proxy('login:password|host:port')
Proxy('http://login:password@host:port')
...
- for mobile proxy you can add a refresh (rotation) url
Proxy('host:port:login:password[https://rotate.my-proxy.io?api_key=your_api_key]')
Proxy('http://login:password@host:port[https://rotate.my-proxy.io?api_key=your_api_key]')
...
P.S. The string parsing method was copied from better-proxy.
New in v 2.0:
- both
requestsandaiohttpchanged to one libhttpx - new methods
Proxy.check()andProxy.acheck() - proxy checking functions got a new parameter
raise_on_errordefaults to False - now it is possible to inherit from the Proxy class and pass the new class to the Pydantic BaseModel without an error
check_proxy()now is fully synccheck_proxies()can be called with arguse_async=False(not recommended but if u really need this u can use it)- tests added
- a lot of small fixes
New in v 2.1:
ClientandAsyncClientadded- new methods
Proxy.get_client()andProxy.get_async_client()
Common use cases
- aiohttp
import aiohttp
from proxystr import Proxy
proxy = Proxy("login:password@210.173.88.77:3001")
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url, proxy=proxy.url) as response:
return await response.text()
- aiohttp-socks
import aiohttp
from aiohttp_socks import ProxyConnector
from proxystr import Proxy
proxy = Proxy("socks5://login:password@210.173.88.77:3001")
async def fetch(url):
connector = ProxyConnector.from_url(proxy.url)
async with aiohttp.ClientSession(connector=connector) as session:
async with session.get(url) as response:
return await response.text()
- requests
import requests
from proxystr import Proxy
proxy = Proxy("login:password@210.173.88.77:3001")
def fetch(url):
response = requests.get(url, proxies=proxy.dict)
return response.text
- httpx
import httpx
from proxystr import Proxy
proxy = Proxy("login:password@210.173.88.77:3001")
async def fetch(url):
async with httpx.AsyncClient(proxy=proxy.url, follow_redirects=True) as client:
response = await client.get(url)
return response.text
# or
def sync_fetch(url):
with httpx.Client(proxy=proxy.url, follow_redirects=True) as client:
return client.get(url).text
# or
def simple_fetch(url):
return httpx.get(url, proxy=proxy.url, follow_redirects=True).text
- httpx-socks
import httpx
from httpx_socks import AsyncProxyTransport, SyncProxyTransport
from proxystr import Proxy
proxy = Proxy("socks5://login:password@210.173.88.77:3001")
async def fetch(url):
transport = AsyncProxyTransport.from_url(proxy.url)
async with httpx.AsyncClient(transport=transport, follow_redirects=True) as client:
response = await client.get(url)
return response.text
# or
def sync_fetch(url):
transport = SyncProxyTransport.from_url(proxy.url)
with httpx.Client(transport=transport, follow_redirects=True) as client:
return client.get(url).text
- httpx wrapped by proxystr
from proxystr import Proxy, Client, AsyncClient
proxy = Proxy("log:pass@210.173.88.77:3001") # or "socks5://log:pass@210.173.88.77:3001"
async def fetch(url):
async with AsyncClient(proxy=proxy) as client:
response = await client.get(url)
return response.text
# or
async with proxy.get_async_client() as client:
response = await client.get(url)
return response.text
# or
def sync_fetch(url):
with Client(proxy=proxy) as client:
return client.get(url).text
# or
with proxy.get_client() as client:
return client.get(url).text
- playwright
from playwright.async_api import async_playwright, Playwright
from proxystr import Proxy
proxy = Proxy("login:password@210.173.88.77:3001")
async def fetch(playwright: Playwright, url):
chromium = playwright.chromium
browser = await chromium.launch(proxy=proxy.playwright)
...
P.S. Playwright communication was copied from better-proxy.
Object representation
import json
from proxystr import Proxy
proxy = Proxy("login:password@210.173.88.77:3001")
print(proxy) # according to Proxy.default_pattern
print(json.dumps(proxy))
print({'proxy': proxy})
print(proxy.url)
print(proxy.dict)
print(proxy.json())
print(proxy.playwright())
Output:
login:password@210.173.88.77:3001
"login:password@210.173.88.77:3001"
{'proxy': Proxy(http://login:password@210.173.88.77:3001)}
http://login:password@210.173.88.77:3001
{'http': 'http://login:password@210.173.88.77:3001', 'https': 'http://login:password@210.173.88.77:3001'}
{'protocol': 'http', 'username': 'login', 'password': 'password', 'ip': '210.173.88.77', 'port': 3001, 'rotation_url': None}
{'server': 'http://210.173.88.77:3001', 'password': 'password', 'username': 'login'}
- You can change default pattern
import json
from proxystr import Proxy
Proxy.set_default_pattern('protocol://ip:port:username:password[rotation_url]')
proxy = Proxy("login:password@210.173.88.77:3001[https://rotate.my-proxy.io?api_key=your_api_key]")
print(proxy)
print(json.dumps(proxy))
print({'proxy': proxy})
Output:
http://210.173.88.77:3001:login:password[https://rotate.my-proxy.io/?api_key=your_api_key]
"http://210.173.88.77:3001:login:password[https://rotate.my-proxy.io/?api_key=your_api_key]"
{'proxy': Proxy(http://login:password@210.173.88.77:3001)}
Proxy checking
from proxystr import Proxy, check_proxies, read_proxies
proxies = [
Proxy("login:password@210.173.88.77:3001"),
Proxy("login:password@210.173.88.78:3002")
]
good_proxies, bad_proxies = check_proxies(proxies)
# or in raw str format:
good_proxies, bad_proxies = check_proxies(["log:pass@210.173.88.77:3001", "log:pass@210.173.88.78:3002"])
# or read from file and check
good_proxies, bad_proxies = check_proxies(read_proxies('proxies.txt'))
# or for single proxy:
proxy = Proxy("login:password@210.173.88.77:3001")
if proxy.check():
'''do_something'''
Another available functions: check_proxy for single proxy, acheck_proxy and acheck_proxies for async use cases
Note that sync check_proxies() by default just wraps async acheck_proxies()
- You can get a proxy info while checking it
from proxystr import Proxy, check_proxies
proxies = [
Proxy("login:password@210.173.88.77:3001"),
Proxy("login:password@210.173.88.78:3002")
]
good_proxies, bad_proxies = check_proxies(proxies, with_info=True)
for proxy, info in good_proxies:
print(info)
# or for single proxy:
proxy = Proxy("login:password@210.173.88.77:3001")
print(proxy.get_info())
output
{'country': 'Germany', 'countryCode': 'DE', 'city': 'Frankfurt am Main', 'query': '210.173.88.77'}
{'country': 'Germany', 'countryCode': 'DE', 'city': 'Frankfurt am Main', 'query': '210.173.88.78'}
You can add yours
fieldsargument to get another info. More details on ip-api.com
Another simple way to get info is a sync method
proxy.get_info() -> Dictor asyncawait proxy.aget_info() -> Dict
Pydantic compatibility
from proxystr import Proxy
from pydantic import BaseModel
class Account(BaseModel):
number: int
proxy: Proxy | None = None
for account in [
Account(number=1, proxy=Proxy('login:password@210.173.88.77:3001')),
Account(number=2, proxy='login:password@210.173.88.77:3001')
]:
print(account)
print(account.model_dump())
output
number=1 proxy=Proxy(http://login:password@210.173.88.77:3001)
{'number': 1, 'proxy': Proxy(http://login:password@210.173.88.77:3001)}
number=2 proxy=Proxy(http://login:password@210.173.88.77:3001)
{'number': 2, 'proxy': Proxy(http://login:password@210.173.88.77:3001)}
Set and equal support
from proxystr import Proxy
p1 = Proxy('login:password@210.173.88.77:3001')
p2 = Proxy('210.173.88.77:3001:login:password')
print(p1 == '210.173.88.77:3001:login:password') # --> True
print(p1 == p2) # --> True
print(p1 is p2) # --> False
print(set((p1, p2))) # --> {Proxy(http://login:password@210.173.88.77:3001)}
Available properties and functions
class Proxy
| name | type | returns | description |
|---|---|---|---|
| ip | attribute | str | |
| host | property | str | same as ip |
| port | attribute | int | |
| username | attribute | str | |
| login | property | str | same as username |
| password | attribute | str | |
| rotation_url | attribute | str | for mobile proxy |
| refresh_url | property | str | same as rotation_url |
| url | property | str | protocol://login:password@ip:port |
| dict | property | dict | urls for requests session |
| proxies | property | dict | same as dict |
| server | property | str | protocol://host:port |
| playwright | property | TypedDict | |
| json() | method | dict | all attributes |
| get_info() | method | dict | info like country etc. |
| aget_info() | method | dict | async version of get_info() |
| check() | method | bool | simple proxy check |
| acheck() | method | bool | async version of check() |
| set_default_pattern() | classmethod | None | changes __str__ pattern |
| rotate() | method | bool | sync function to rotate mobile proxy |
| arotate() | method | bool | async version of rotate() |
| refresh() | method | bool | same as rotate |
| arefresh() | method | bool | same as arotate |
| get_client() | method | httpx.Client | with proxy included |
| get_async_client() | method | httpx.AsyncClient | with proxy included |
module proxystr
| name | input | output | description |
|---|---|---|---|
| Proxy | str | Proxy object (str) | |
| Client | **kwargs | httpx.Client object | arg proxy takes http and socks proxy |
| AsyncClient | **kwargs | httpx.AsyncClient object | arg proxy takes http and socks proxy |
| check_proxy() | Proxy | Tuple[Proxy, bool] | |
| check_proxies() | Sequence[Proxy] | Tuple[List[Proxy], List[Proxy]] | returns good and failed proxies |
| acheck_proxy() | -- | -- | async version of check_proxy() |
| acheck_proxies() | -- | -- | async version of check_proxies() |
| read_proxies() | str('filepath') | List[Proxy] | read proxies from file |
Support
Developed by MrSmith06: telegram | gtihub
If you find this project helpful, feel free to leave a tip!
- EVM address (metamask):
0x6201d7364F01772F8FbDce67A9900d505950aB99
Metadata
Release files for proxystr 2.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| proxystr-2.1.3.tar.gz | 9.4 kB | Without provenance | Details for proxystr-2.1.3.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| proxystr-2.1.3-py3-none-any.whl | Python 3 | none | any | Details for proxystr-2.1.3-py3-none-any.whl |
Total release size: 19.9 kB
Release files / proxystr-2.1.3.tar.gz
| Download URL | proxystr-2.1.3.tar.gz |
|---|---|
| Size | 9.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d6da2c2dc1b8860059aaba049ab29bcd665437936fa7684fb637b962f542fff3
|
|
BLAKE2b-256 checksum How to use checksums |
4af7b7fe0a7842c2cef334368ca2d7e3d9e5f5dab7595bc226ec2568972b10bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.3 CPython/3.10.11 Windows/10
|
Release files / proxystr-2.1.3-py3-none-any.whl
| Download URL | proxystr-2.1.3-py3-none-any.whl |
|---|---|
| Size | 10.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4782add5cbe9a623fc0983b77e094c3b1e250c94677a0f4cf4dad6c4b2a17094
|
|
BLAKE2b-256 checksum How to use checksums |
1d50cd85c997a5f16a0e9971e9a6e59c025a7bfce5cb3d0381726161a374e079
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.3 CPython/3.10.11 Windows/10
|
Security for proxystr 2.1.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.