← Back to Blog

HTTPX के लिए Python में असिंक्रोनस प्रॉक्सी: रोटेशन, HTTP/2 और नए लोगों की 5 गलतियाँ

हम समझाते हैं कि httpx में प्रॉक्सी रोटेशन को सही तरीके से कैसे सेट करें, HTTP/2 को कैसे सक्रिय करें और उन समस्याओं से कैसे बचें जो 90% शुरुआती पार्सर डेवलपर्स का सामना करते हैं।

📅October 17, 2026

httpx पुस्तकालय Python में असिंक्रोनस HTTP अनुरोधों के लिए मानक बन गया है, लेकिन प्रॉक्सी के साथ काम करते समय इसमें कुछ बारीकियाँ हैं जो प्रोडक्शन में पार्सर्स को तोड़ देती हैं। हम समझेंगे कि असिंक्रोनस प्रॉक्सी रोटेशन को कैसे सेटअप करें, HTTP/2 को कैसे सक्षम करें और क्यों आपका स्क्रिप्ट हर 50-100 अनुरोधों पर क्रैश हो जाता है।

क्यों httpx, न कि requests या aiohttp

requests समकालिक है और HTTP/2 को डिफ़ॉल्ट रूप से समर्थन नहीं करता। aiohttp असिंक्रोनस है, लेकिन वहाँ प्रॉक्सी की सेटिंग कम मित्रवत है, और HTTP/2 का समर्थन बिल्कुल नहीं है। httpx दोनों सवालों का समाधान करता है: एक समान API के साथ समकालिक और असिंक्रोनस क्लाइंट, h2 एक्सटेंशन के माध्यम से HTTP/2 का स्वदेशी समर्थन, और परिवहन स्तर पर प्रॉक्सी के साथ लचीला काम।

मार्केटप्लेस (Wildberries, Ozon, Avito) के लिए पार्सिंग कार्यों, सोशल मीडिया API से डेटा एकत्र करने या प्रतिस्पर्धियों की कीमतों की निगरानी के लिए असिंक्रोनस होना महत्वपूर्ण है - यह अनुक्रमिक अनुरोधों की तुलना में गति में गुणात्मक वृद्धि देता है। लेकिन प्रॉक्सी की सही रोटेशन और कनेक्शन प्रबंधन के बिना, असिंक्रोनसता नई समस्याओं का स्रोत बन जाती है: कनेक्शन पूल का समाप्त होना, लटकी हुई कोरूटीन, फ़ाइल डिस्क्रिप्टर का रिसाव।

दूसरा महत्वपूर्ण बिंदु - HTTP/2 एक ही TCP कनेक्शन में कई अनुरोधों को मल्टीप्लेक्स करने में सक्षम है, जो लक्षित सर्वर पर लोड को कम करता है और कुछ सरल एंटी-बॉट सिस्टम को बायपास करने में मदद करता है, जो एक IP से TCP हैंडशेक की संख्या पर नजर रखते हैं।

httpx में प्रॉक्सी की बुनियादी सेटिंग

httpx 0.26+ संस्करण से प्रॉक्सी सेटिंग का सिंटैक्स बदल गया है - proxies शब्दकोश के बजाय proxy पैरामीटर का उपयोग किया जाता है। यदि आप पुराने ट्यूटोरियल देख रहे हैं, तो यह भ्रम का एक सामान्य स्रोत है।

import httpx
import asyncio

PROXY_URL = "http://user:[email protected]:8000"

async def fetch(url: str):
    async with httpx.AsyncClient(proxy=PROXY_URL, timeout=15.0) as client:
        response = await client.get(url)
        return response.status_code, response.text[:200]

asyncio.run(fetch("https://httpbin.org/ip"))

यदि HTTP और HTTPS ट्रैफ़िक के लिए प्रॉक्सी को विभाजित करना है या विभिन्न डोमेन के लिए विभिन्न प्रॉक्सी सेट करना है, तो httpx.Client(mounts=...) का उपयोग करें - परिवहन URL पैटर्न के अनुसार माउंट किए जाते हैं:

mounts = {
    "http://": httpx.AsyncHTTPTransport(proxy="http://user:[email protected]:8000"),
    "https://": httpx.AsyncHTTPTransport(proxy="http://user:[email protected]:8000"),
}

async with httpx.AsyncClient(mounts=mounts) as client:
    response = await client.get("https://example.com")

लॉगिन और पासवर्ड के माध्यम से प्रमाणीकरण के लिए http://user:pass@host:port प्रारूप HTTP प्रॉक्सी के लिए स्थिरता से काम करता है। SOCKS5 के लिए आपको अतिरिक्त रूप से httpx[socks] स्थापित करने की आवश्यकता होगी, अन्यथा आपको रनटाइम में ImportError मिलेगा, न कि कोड लिखने के चरण में - यह एक जाल है जिसमें कई लोग फंस जाते हैं।

असिंक्रोनस प्रॉक्सी रोटेशन: कार्यशील कोड

प्रॉक्सी रोटेशन में मुख्य गलती - प्रत्येक अनुरोध पर नया AsyncClient

import httpx
import asyncio
import itertools
import random

PROXIES = [
    "http://user:[email protected]:8000",
    "http://user:[email protected]:8000",
    "http://user:[email protected]:8000",
]

class ProxyPool:
    def __init__(self, proxies: list[str]):
        self.clients = [
            httpx.AsyncClient(proxy=p, timeout=httpx.Timeout(15.0, connect=5.0))
            for p in proxies
        ]
        self._cycle = itertools.cycle(self.clients)

    def get_client(self) -> httpx.AsyncClient:
        return next(self._cycle)  # राउंड-रॉबिन
        # यादृच्छिक चयन के लिए: random.choice(self.clients)

    async def close_all(self):
        for client in self.clients:
            await client.aclose()

async def fetch_with_retry(pool: ProxyPool, url: str, retries: int = 3):
    for attempt in range(retries):
        client = pool.get_client()
        try:
            response = await client.get(url)
            if response.status_code == 200:
                return response.text
        except (httpx.ConnectTimeout, httpx.ProxyError, httpx.ReadTimeout):
            await asyncio.sleep(0.5 * (attempt + 1))
            continue
    return None

async def main():
    pool = ProxyPool(PROXIES)
    urls = [f"https://example.com/page/{i}" for i in range(100)]

    sem = asyncio.Semaphore(20)  # समांतरता को सीमित करें

    async def bound_fetch(url):
        async with sem:
            return await fetch_with_retry(pool, url)

    results = await asyncio.gather(*(bound_fetch(u) for u in urls))
    await pool.close_all()
    return results

asyncio.run(main())

यह पैटर्न तीन समस्याओं को एक साथ हल करता है: keep-alive के माध्यम से TCP कनेक्शनों का पुनः उपयोग करता है, प्रॉक्सी पर राउंड-रॉबिन तरीके से लोड वितरित करता है और समांतरता को सीमित करता है ताकि लक्षित सर्वर को न गिराए और रेट-लिमिट के कारण बैन न हो।

प्रोडक्शन पार्सर्स के लिए, जो Wildberries, Ozon या Instagram API के साथ काम करते हैं, यह महत्वपूर्ण है कि प्रॉक्सी का पूल पर्याप्त बड़ा और भौगोलिक रूप से विविध हो - अन्यथा एक ही सबनेट के भीतर रोटेशन ब्लॉक होने से नहीं बचाएगा। यहाँ रिहायशी प्रॉक्सी अच्छे होते हैं, क्योंकि उनके पास वास्तविक उपयोगकर्ताओं के IP होते हैं और वे एंटी-बॉट सिस्टम के फ़िल्टर में कम आते हैं, जो ASN और रेंज की प्रतिष्ठा का विश्लेषण करते हैं।

httpx में HTTP/2: क्यों और कैसे सक्षम करें

डिफ़ॉल्ट रूप से httpx HTTP/1.1 का उपयोग करता है। HTTP/2 को सक्षम करने के लिए, आपको एक्सटेंशन स्थापित करना होगा और स्पष्ट रूप से फ़्लैग पास करना होगा:

# pip install httpx[http2]

async with httpx.AsyncClient(http2=True, proxy=PROXY_URL) as client:
    response = await client.get("https://example.com")
    print(response.http_version)  # "HTTP/2" की अपेक्षा करें

एक महत्वपूर्ण बिंदु: सभी प्रॉक्सी HTTP/2 टनलिंग को सही तरीके से समर्थन नहीं करते। कुछ सस्ते डेटा सेंटर प्रॉक्सी केवल HTTP/1.1 प्रॉक्सी के रूप में काम करते हैं, भले ही अंतिम सर्वर HTTP/2 का समर्थन करता हो - इस मामले में httpx चुपचाप CONNECT टनल के माध्यम से HTTP/1.1 पर वापस लौट जाएगा, और आप हमेशा इसे स्पष्ट रूप से response.http_version की जांच किए बिना नहीं देखेंगे।

HTTP/2 तीन परिदृश्यों में वास्तविक लाभ देता है: जब आप एक ही डोमेन पर कई अनुरोध करते हैं (एक कनेक्शन में मल्टीप्लेक्सिंग विलंबता को कम करता है), जब एंटी-बॉट सुरक्षा के लिए अनुरोधों की दृश्यता को कम करना महत्वपूर्ण होता है (एक IP से कम TCP हैंडशेक अधिक स्वाभाविक दिखता है), और जब लक्षित वेबसाइट स्वयं HTTP/2 की मांग करती है और HTTP/1.1 पर ग्राहकों को त्रुटियाँ या कटे हुए सामग्री लौटाती है - यह कभी-कभी Cloudflare पर साइटों में होता है।

उन कार्यों के लिए, जहाँ प्रॉक्सी के माध्यम से HTTP/2 कनेक्शनों की गति और स्थिरता महत्वपूर्ण है, विशेष डेटा सेंटर प्रॉक्सी अधिक उपयुक्त होते हैं - ये रिहायशी प्रॉक्सी की तुलना में तेज होते हैं और आमतौर पर आधुनिक प्रोटोकॉल की टनलिंग को सही तरीके से समर्थन करते हैं।

httpx में प्रॉक्सी के साथ 5 सामान्य गलतियाँ

1. प्रत्येक अनुरोध पर क्लाइंट का पुनर्निर्माण

async with httpx.AsyncClient(...) as client: await client.get(url) जैसे कोड को लूप के अंदर रखना - यह एक एंटी-पैटर्न है। प्रत्येक क्लाइंट का निर्माण एक नया TCP कनेक्ट, नया TLS हैंडशेक, कनेक्शन पूलिंग की पूरी अनदेखी है। 1000 अनुरोधों पर, सही और गलत दृष्टिकोण के बीच गति में अंतर 5-10 गुना हो सकता है।

2. टाइमआउट का अभाव या डिफ़ॉल्ट रूप से बहुत बड़े टाइमआउट

डिफ़ॉल्ट रूप से httpx सभी पर 5 सेकंड का टाइमआउट सेट करता है - कनेक्ट, पढ़ना, लिखना, पूल। अस्थिर प्रॉक्सी के माध्यम से काम करते समय यह कनेक्ट के लिए बहुत कम है, लेकिन पढ़ने के लिए बहुत अधिक है, यदि प्रॉक्सी बस "लटकी" है। टाइमआउट को स्पष्ट रूप से विभाजित करें:

timeout = httpx.Timeout(
    connect=5.0,
    read=10.0,
    write=10.0,
    pool=5.0
)
client = httpx.AsyncClient(proxy=PROXY_URL, timeout=timeout)

3. कनेक्शन पूल के सीमाओं की अनदेखी

जब बहुत सारे समांतर कार्य होते हैं (500+ कोरूटीन पर गेदर बिना सेमाफोर) httpx PoolTimeout फेंकने लगता है, क्योंकि पूल में कनेक्शनों की सीमा (डिफ़ॉल्ट रूप से 100) समाप्त हो गई है। सीमाओं को स्पष्ट रूप से httpx.Limits(max_connections=200, max_keepalive_connections=50) के माध्यम से सेट करें और हमेशा समांतरता को नियंत्रित करने के लिए सेमाफोर का उपयोग करें।

4. परिणामों को समझे बिना verify को बंद करना

कई लोग Stack Overflow से verify=False की नकल करते हैं ताकि प्रॉक्सी के माध्यम से MITM प्रमाणपत्रों के साथ काम करते समय SSL त्रुटियों से छुटकारा मिल सके। यह "मध्यवर्ती व्यक्ति" हमलों के लिए रास्ता खोलता है और समझौता किए गए प्रॉक्सी के माध्यम से डेटा लीक का कारण बन सकता है। यदि प्रॉक्सी को विशेष प्रमाणपत्र की आवश्यकता है - इसे स्पष्ट रूप से verify="/path/to/cert.pem" के माध्यम से जोड़ें, न कि पूरी तरह से सत्यापन को बंद करें।

5. क्लाइंट बंद नहीं करना और फ़ाइल डिस्क्रिप्टर का रिसाव

यदि आप मैन्युअल रूप से क्लाइंट का पूल बनाते हैं (जैसा कि ऊपर के उदाहरण में), तो काम खत्म होने पर प्रत्येक के लिए await client.aclose() को कॉल करना न भूलें। लंबे समय तक चलने वाले स्क्रिप्ट बिना स्पष्ट रूप से कनेक्शन बंद किए ऑपरेटिंग सिस्टम के खोले गए फ़ाइल डिस्क्रिप्टर की सीमा (आमतौर पर Linux पर डिफ़ॉल्ट रूप से 1024) तक पहुँच जाते हैं, और पार्सर कुछ घंटों के काम के बाद रहस्यमय त्रुटि Too many open files के साथ क्रैश हो जाता है।

पार्सिंग के लिए कौन सा प्रॉक्सी प्रकार चुनें

प्रॉक्सी का चयन सीधे इस पर प्रभाव डालता है कि आप ऊपर की सूची में कितनी गलतियाँ देखेंगे - अस्थिर प्रॉक्सी टाइमआउट और कनेक्शन टूटने का कारण बनती हैं, भले ही कोड सही तरीके से लिखा गया हो।

प्रॉक्सी का प्रकार गति ब्लॉक होने का जोखिम कब उपयोग करें
डेटा सेंटर उच्च सुरक्षित साइटों पर उच्च Open API, कमजोर एंटी-बॉट सुरक्षा
रिहायशी मध्यम कम Wildberries, Ozon, सोशल मीडिया
मोबाइल मध्यम-निम्न न्यूनतम Instagram, TikTok API, कड़ी सुरक्षा

असिंक्रोनस पार्सिंग के लिए API पर उच्च गति के अनुरोधों के साथ डेटा सेंटर प्रॉक्सी आर्थिक रूप से लाभदायक विकल्प बने रहते हैं - मुख्य बात यह है कि ऊपर दिए गए कोड में दिखाए अनुसार लोड को समान रूप से वितरित करें।

प्रोडक्शन से पहले चेकलिस्ट

  • httpx क्लाइंट एक बार बनाए जाते हैं और पुनः उपयोग किए जाते हैं, न कि प्रत्येक अनुरोध पर
  • टाइमआउट को connect/read/write/pool में विभाजित किया गया है, न कि डिफ़ॉल्ट का उपयोग किया गया है
  • समांतरता को asyncio.Semaphore के माध्यम से सीमित किया गया है
  • कनेक्शन पूल की सीमाएँ वास्तविक लोड के अनुसार सेट की गई हैं
  • ProxyError, ConnectTimeout, ReadTimeout के साथ पुनः प्रयास करने की लॉजिक है
  • सभी क्लाइंट को समाप्ति पर aclose() के माध्यम से स्पष्ट रूप से बंद किया जाता है
  • verify=False का उपयोग बिना अत्यावश्यकता के नहीं किया जाता है
  • HTTP/2 को जानबूझकर सक्षम किया गया है और response.http_version के माध्यम से जांचा गया है

निष्कर्ष

httpx प्रॉक्सी और HTTP/2 के साथ असिंक्रोनस काम के लिए एक शक्तिशाली उपकरण प्रदान करता है, लेकिन क्लाइंट पूल, टाइमआउट और कनेक्शन सीमाओं की सावधानीपूर्वक सेटिंग की आवश्यकता होती है। प्रोडक्शन में पार्सर्स के अधिकांश क्रैश का कारण पुस्तकालय नहीं, बल्कि आर्किटेक्चरल गलतियाँ हैं: क्लाइंट का पुनर्निर्माण, समांतरता की कमी और प्रॉक्सी की गलत अपवाद प्रबंधन।

यदि आप मार्केटप्लेस या सोशल मीडिया API के लिए पार्सर बना रहे हैं, जो संदिग्ध गतिविधियों की सक्रिय रूप से निगरानी करते हैं, तो प्रॉक्सी की बुनियादी ढांचे की स्थिरता कोड से कम महत्वपूर्ण नहीं है। ऐसे कार्यों के लिए रिहायशी प्रॉक्सी पर विचार करना चाहिए - वे सस्ते डेटा सेंटर पूलों की तुलना में उच्च IP प्रतिष्ठा के कारण ProxyError और ConnectTimeout की त्रुटियों को कम करते हैं।