Python में Async प्रॉक्सी रोटेशन: httpx और aiohttp (2026 गाइड)

12 जून 2026 को प्रकाशित · ≈10 मिनट पढ़ें

Async स्क्रेपिंग वह जगह है जहाँ प्रॉक्सी सेटअप चुपचाप बिखर जाते हैं। requests के साथ आप प्रति कॉल एक IP रोटेट करते हैं और आगे बढ़ जाते हैं; asyncio के साथ अचानक आपके पास 200 अनुरोध उड़ान में होते हैं, सभी को अपने स्वयं के exit, अपनी स्वयं की session affinity, और एक target द्वारा 403 फेंकने पर अपने स्वयं के retry की ज़रूरत होती है। ग़लती करें और आप या तो एक IP को बैन तक पीट देते हैं या मध्य-फ़्लो रोटेट करके हर लॉगिन session को चीर देते हैं।

यह गाइड वे पैटर्न दिखाती है जो वास्तव में concurrency पर टिकते हैं: httpx और aiohttp में प्रति-अनुरोध रोटेशन, एक सीमित वर्कर पूल, stateful फ़्लो के लिए sticky sessions, और block-aware retries — काम करने वाले कोड के साथ जिसे आप पेस्ट कर सकते हैं।

Async प्रॉक्सी समस्या को क्यों बदल देता है

एक सिंक्रोनस स्क्रेपर एक समय में एक प्रॉक्सी को छूता है, इसलिए "हर अनुरोध पर रोटेट करें" तुच्छ रूप से सही है। Async एक साथ तीन धारणाएँ तोड़ देता है:

httpx: प्रति-अनुरोध प्रॉक्सी रोटेशन

httpx.AsyncClient प्रति क्लाइंट एक प्रॉक्सी बाँधता है, इसलिए रोटेट करने के लिए आप प्रति अनुरोध प्रॉक्सी चुनते हैं और exit द्वारा कीड किए गए क्लाइंटों के एक छोटे पूल से रूट करते हैं:

import asyncio, itertools, httpx

PROXIES = [
    "socks5h://USERNAME:[email protected]:913",
    "socks5h://USERNAME:[email protected]:913",
    "socks5h://USERNAME:[email protected]:913",
]
pool = itertools.cycle(PROXIES)

# One reusable client per exit (connection pooling stays intact)
clients = {p: httpx.AsyncClient(proxy=p, timeout=30) for p in PROXIES}

async def fetch(url):
    proxy = next(pool)
    r = await clients[proxy].get(url)
    return r.status_code, r.text

async def main(urls):
    results = await asyncio.gather(*(fetch(u) for u in urls))
    for client in clients.values():
        await client.aclose()
    return results

प्रति exit एक क्लाइंट को पुनः उपयोग करना HTTP/2 और connection pooling को जीवित रखता है, बजाय हर अनुरोध पर एक नया handshake चुकाने के। ध्यान दें कि httpx>=0.28 ने क्लाइंट पर proxies= का नाम बदलकर proxy= कर दिया।

aiohttp: अनुरोध के ज़रिए रोटेशन

aiohttp यहाँ सरल है — एक एकल ClientSession प्रति अनुरोध एक proxy= तर्क लेता है, इसलिए आप इनलाइन रोटेट करते हैं:

import asyncio, itertools, aiohttp

pool = itertools.cycle(PROXIES)  # http:// or socks5h:// (needs aiohttp-socks for SOCKS)

async def fetch(session, url):
    proxy = next(pool)
    async with session.get(url, proxy=proxy, timeout=aiohttp.ClientTimeout(total=30)) as r:
        return r.status, await r.text()

async def main(urls):
    async with aiohttp.ClientSession() as session:
        return await asyncio.gather(*(fetch(session, u) for u in urls))

aiohttp HTTP प्रॉक्सी को नेटिव रूप से समझता है; socks5h:// के लिए aiohttp-socks जोड़ें और एक ProxyConnector पास करें।

Semaphore के साथ Concurrency सीमित करें

असीमित gather एक साथ आपके पूल के हर IP को फ़्लैग करवाने का सबसे तेज़ तरीका है। इसे सीमित करें ताकि हर exit समानांतर अनुरोधों की एक इंसान-संभावित संख्या ढोए:

sem = asyncio.Semaphore(10)   # at most 10 in flight

async def fetch_capped(session, url):
    async with sem:
        return await fetch(session, url)

अंगूठे का नियम: concurrency को अपने पास मौजूद विशिष्ट exit की संख्या के बराबर या उससे कम रखें, ताकि आप एक एकल रेज़िडेंशियल IP पर कई समानांतर अनुरोध न ढेर करें।

Stateful फ़्लो के लिए Sticky Sessions

रोटेशन अंदर पहुँचने के लिए है; sticky sessions अंदर बने रहने के लिए हैं। एक लॉगिन, एक कार्ट, कुछ भी जो cookie-बद्ध है, उसे पूरे क्रम के लिए एक exit पकड़े रखना चाहिए। प्रति अनुरोध के बजाय प्रति task प्रॉक्सी पिन करें:

async def run_account(account, proxy):
    # Same exit IP for every step of this account's flow
    async with httpx.AsyncClient(proxy=proxy, timeout=30) as client:
        await client.post("https://target.site/login", data=account.creds)
        await client.get("https://target.site/dashboard")
        await client.post("https://target.site/cart", json=account.order)

async def main(accounts):
    # One sticky exit per account, accounts run concurrently
    await asyncio.gather(*(run_account(a, p)
                           for a, p in zip(accounts, itertools.cycle(PROXIES))))

एक ऐसे प्रदाता का उपयोग करें जो sticky रेज़िडेंशियल sessions का समर्थन करता है ताकि वही exit task के पूरे जीवनकाल के लिए पकड़ा रहे, आपके नीचे चुपचाप रोटेट न हो।

Block-Aware Retries

Concurrency पर आप एक 200 पर भरोसा नहीं कर सकते — एंटी-बॉट सिस्टम एक challenge बॉडी के साथ 200 लौटाते हैं। ब्लॉक का पता लगाएँ और एकल फ़ेल हुए task को एक नए exit पर retry करें:

BLOCK_MARKERS = ("just a moment", "/cdn-cgi/challenge-platform",
                 "datadome", "px-captcha", "access denied")

def looks_blocked(status, text):
    return status in (403, 429, 503) or any(m in text[:4000].lower() for m in BLOCK_MARKERS)

async def fetch_retry(url, attempts=4):
    for _ in range(attempts):
        proxy = next(pool)
        async with httpx.AsyncClient(proxy=proxy, timeout=30) as c:
            r = await c.get(url)
            if not looks_blocked(r.status_code, r.text):
                return r
        await asyncio.sleep(0.5)
    raise RuntimeError(f"blocked after {attempts} exits: {url}")

फ़िंगरप्रिंट को अब भी मेल खाना है

एक पकड़ जिसे async हल नहीं करता: httpx और aiohttp दोनों Python के TLS स्टैक पर बैठते हैं, इसलिए वे एक ऐसा JA3 भेजते हैं जो कोई असली ब्राउज़र नहीं बनाता। एक साफ़ रेज़िडेंशियल IP पर एक परफ़ेक्ट रोटेशन पूल भी handshake पर ऑटोमेशन के रूप में फ़िंगरप्रिंट हो जाता है। async रोटेशन को TLS impersonation के साथ जोड़ें — देखें curl_cffi के साथ TLS फ़िंगरप्रिंटिंग को बायपास करें, और अपने exit का JA3 + ASN www.jibaoproxy.com/tools/fingerprint.html पर सत्यापित करें।

चेकलिस्ट

सभी IP प्रोडक्ट्स के लिए · किसी भी समय उपलब्ध नोड्स का विशाल पूल

अभी साइन अप करें और अपने रिचार्ज पर 100% तक का रिबेट पाएं

नए यूज़र्स को साइन अप पर 500MB मिलते हैं, साथ ही पहली रिचार्ज पर बोनस। सीमित समय की पेशकश।