Skip to main content

Use a proxy as a string, but achieve broad functionality for various scenarios

Project description

ProxyStr

Telegram channel

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 requests and aiohttp changed to one lib httpx
  • new methods Proxy.check() and Proxy.acheck()
  • proxy checking functions got a new parameter raise_on_error defaults 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 sync
  • check_proxies() can be called with arg use_async=False (not recommended but if u really need this u can use it)
  • tests added
  • a lot of small fixes

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
  • 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

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 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)

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 fields argument to get another info. More details on ip-api.com

Another simple way to get info is a sync method proxy.get_info() -> Dict or async await 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

module proxystr

name input output description
Proxy str Proxy object (str)
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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

proxystr-2.0.4.tar.gz (8.9 kB view hashes)

Uploaded Source

Built Distribution

proxystr-2.0.4-py3-none-any.whl (10.1 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page