यदि आप Python में प्रॉक्सी के माध्यम से वेबसाइटों को पार्स कर रहे हैं या अनुरोधों को स्वचालित कर रहे हैं, तो आप तीन
क्लासिक त्रुटियों का सामना करेंगे: ProxyError,
SSLError: WRONG_VERSION_NUMBER और HTTP
407 Proxy Authentication Required. इस लेख में हम
प्रत्येक की वजह का विश्लेषण करेंगे और सुधार के लिए कार्यशील कोड दिखाएंगे।
कैसे requests प्रॉक्सी के साथ काम करता है: बुनियादी सिंटैक्स
requests पुस्तकालय प्रॉक्सी को एक शब्दकोश के माध्यम से स्वीकार करता है
proxies, जहाँ कुंजी अनुरोध की स्कीमा होती है
(http और https),
और मान प्रॉक्सी सर्वर का URL वैकल्पिक प्रमाणीकरण के साथ होता है।
import requests
proxies = {
"http": "http://user:password@proxy_host:port",
"https": "http://user:password@proxy_host:port",
}
response = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10)
print(response.json())
ध्यान दें: HTTPS अनुरोधों के लिए भी प्रॉक्सी स्कीमा आमतौर पर http:// के रूप में निर्दिष्ट की जाती है,
क्योंकि अधिकांश प्रॉक्सी सर्वर HTTP प्रोटोकॉल के माध्यम से CONNECT टनल को स्वीकार करते हैं, न कि इसे SSL में लपेटते हैं। यदि आप निर्दिष्ट करते हैं
https:// प्रॉक्सी के लिए जो इसका समर्थन नहीं करता है — आप
SSLError प्राप्त करेंगे, जिसका विश्लेषण नीचे किया जाएगा।
यदि आप SOCKS5 प्रॉक्सी के साथ काम कर रहे हैं, तो अतिरिक्त पैकेज की आवश्यकता होगी:
pip install requests[socks]
# और प्रॉक्सी का सिंटैक्स बदल जाता है:
proxies = {
"http": "socks5://user:password@proxy_host:port",
"https": "socks5://user:password@proxy_host:port",
}
ProxyError: कारण और समाधान
requests.exceptions.ProxyError प्रॉक्सी सर्वर से कनेक्शन स्थापित करने के प्रयास में उत्पन्न होने वाली
निम्न-स्तरीय नेटवर्क अपवादों के लिए एक लपेटन है। सबसे अधिक बार चार परिदृश्य सामने आते हैं।
1. प्रॉक्सी अनुपलब्ध है या पता/पोर्ट गलत है
requests.exceptions.ProxyError: HTTPSConnectionPool(host='example.com', port=443):
Max retries exceeded with url: / (Caused by ProxyError('Cannot connect to proxy.',
ConnectionResetError(104, 'Connection reset by peer')))
सुनिश्चित करें कि होस्ट और पोर्ट सही ढंग से दर्ज किए गए हैं, और प्रॉक्सी सर्वर वास्तव में चालू है। निदान का सबसे तेज़ तरीका —
curl के माध्यम से कनेक्ट करने का प्रयास करना:
curl -x http://user:password@proxy_host:port https://httpbin.org/ip -v
2. प्रॉक्सी ने आपके अनुरोध को ब्लॉक कर दिया (IP या User-Agent द्वारा बैन)
डेटा सेंटर प्रॉक्सी अक्सर लक्षित वेबसाइटों द्वारा बैन हो जाते हैं क्योंकि उनके IP रेंज एंटी-फ्रॉड सिस्टम द्वारा ज्ञात होते हैं। यदि त्रुटि किसी विशेष वेबसाइट (जैसे, Wildberries, Ozon या सोशल मीडिया) पर स्थिर रूप से उत्पन्न होती है, और सभी वेबसाइटों पर नहीं — तो समस्या प्रॉक्सी में नहीं है, बल्कि इसकी प्रतिष्ठा में है। इस मामले में मदद करता है रेसिडेंशियल प्रॉक्सी पर स्विच करना — वे वास्तविक उपयोगकर्ताओं के IP का उपयोग करते हैं और एंटी-फ्रॉड सिस्टम द्वारा ब्लॉक होने की संभावना कम होती है।
3. समवर्ती कनेक्शनों की सीमा पार हो गई है
यदि आप मल्टी-थ्रेडेड पार्सिंग चला रहे हैं और एक ही प्रॉक्सी के माध्यम से सैकड़ों कनेक्शन खोल रहे हैं, तो सर्वर
अतिरिक्त कनेक्शनों को रिसेट करना शुरू कर सकता है। समाधान है कनेक्शन पूल का उपयोग करना
requests.adapters.HTTPAdapter के माध्यम से, जिसमें
pool_maxsize और
max_retries की सीमा होती है:
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
retries = Retry(total=3, backoff_factor=1, status_forcelist=[502, 503, 504])
adapter = HTTPAdapter(max_retries=retries, pool_connections=20, pool_maxsize=20)
session.mount("http://", adapter)
session.mount("https://", adapter)
response = session.get("https://httpbin.org/ip", proxies=proxies, timeout=10)
4. प्रॉक्सी सर्वर पर टाइमआउट
यदि प्रॉक्सी "लटकी" रहती है तो आप देखेंगे
ProxyError, जो
ReadTimeoutError में लिपटा होता है। टाइमआउट को एक उचित मान
(आमतौर पर 15-30 सेकंड पर्याप्त होता है) तक बढ़ाएं और अपवाद प्रबंधन को अलग से जोड़ें:
try:
response = requests.get(url, proxies=proxies, timeout=20)
except requests.exceptions.ProxyError as e:
print(f"प्रॉक्सी में समस्या: {e}")
except requests.exceptions.Timeout:
print("प्रॉक्सी ने निर्धारित समय में उत्तर नहीं दिया")
SSLError WRONG_VERSION_NUMBER: समस्या का विश्लेषण
यह त्रुटि पहली नज़र में सबसे समझने में कठिन होती है, लेकिन वास्तव में इसका लगभग हमेशा एक ही कारण होता है।
requests.exceptions.SSLError: HTTPSConnectionPool(host='example.com', port=443):
Max retries exceeded with url: / (Caused by SSLError(SSLError(1, '[SSL:
WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1123)')))
WRONG_VERSION_NUMBER का मतलब है कि क्लाइंट ने SSL/TLS हैंडशेक करने का प्रयास किया
वहाँ, जहाँ सर्वर सामान्य HTTP ट्रैफ़िक (बिना एन्क्रिप्शन) की प्रतीक्षा कर रहा था। सबसे अधिक बार कारण गलत है
proxies शब्दकोश में निर्दिष्ट प्रॉक्सी स्कीमा।
आम त्रुटि: प्रॉक्सी सर्वर के पते में https:// का उपयोग करना
http:// के बजाय। अधिकांश HTTP(S) प्रॉक्सी
सामान्य HTTP के माध्यम से कनेक्शन स्वीकार करते हैं, भले ही वे CONNECT तंत्र के माध्यम से HTTPS ट्रैफ़िक को प्रॉक्सी करते हों।
# गलत — WRONG_VERSION_NUMBER को ट्रिगर करेगा
proxies = {
"http": "https://user:password@proxy_host:port",
"https": "https://user:password@proxy_host:port",
}
# सही
proxies = {
"http": "http://user:password@proxy_host:port",
"https": "http://user:password@proxy_host:port",
}
दूसरी आम वजह — पोर्ट, जो भौतिक रूप से TLS का समर्थन नहीं करता है। उदाहरण के लिए, यदि प्रॉक्सी प्रदाता ने पोर्ट 8080 को केवल HTTP ट्रैफ़िक के लिए आवंटित किया है, और आप सीधे (CONNECT को बायपास करते हुए) उस पर TLS कनेक्शन स्थापित करने का प्रयास करते हैं, तो सर्वर सामान्य टेक्स्ट के साथ उत्तर देगा बजाय TLS हैंडशेक के, और क्लाइंट लाइब्रेरी OpenSSL इस त्रुटि को उत्पन्न करेगी। अपने प्रॉक्सी प्रदाता के दस्तावेज़ में जांचें कि प्रत्येक अलग पोर्ट पर कौन से पोर्ट और प्रोटोकॉल (HTTP/HTTPS/SOCKS5) उपलब्ध हैं।
तीसरा विकल्प — आप socket या तृतीय पक्ष का उपयोग कर रहे हैं
प्रॉक्सी के साथ सीधे TCP कनेक्शन के लिए पुस्तकालय, मानक requests तंत्र को बायपास करते हुए। इस मामले में सुनिश्चित करें कि
TLS लपेटन केवल वास्तविक लक्षित वेबसाइट के लिए लागू किया गया है, न कि प्रॉक्सी के साथ स्वयं के कनेक्शन के लिए।
407 Proxy Authentication Required: प्रमाणीकरण
उत्तर कोड 407 — प्रॉक्सी सर्वरों के लिए मानक 401 के समान है। इसका मतलब है कि सर्वर आवश्यक है प्रमाणीकरण, और आप या तो इसे नहीं भेजे हैं, या गलत प्रारूप में भेजे हैं।
विधि 1: URL में सीधे लॉगिन और पासवर्ड
proxies = {
"http": "http://login:password@proxy_host:port",
"https": "http://login:password@proxy_host:port",
}
response = requests.get("https://httpbin.org/ip", proxies=proxies)
यह विधि सबसे सरल है, लेकिन यदि लॉगिन या पासवर्ड में विशेष वर्ण हैं (जैसे @,
:, /),
उन्हें urllib.parse.quote के माध्यम से एस्केप करना आवश्यक है:
from urllib.parse import quote
login = quote("user@domain")
password = quote("p@ssw:ord!")
proxy_url = f"http://{login}:{password}@proxy_host:port"
proxies = {"http": proxy_url, "https": proxy_url}
विधि 2: मैन्युअल रूप से Proxy-Authorization हेडर
यदि प्रॉक्सी प्रदाता एक गैर-मानक प्रमाणीकरण स्कीमा का उपयोग करता है या आपको अधिक नियंत्रण की आवश्यकता है, तो आप हेडर को मैन्युअल रूप से बेस64 एन्कोडिंग के माध्यम से बना सकते हैं:
import base64
import requests
login = "user"
password = "password"
credentials = base64.b64encode(f"{login}:{password}".encode()).decode()
headers = {
"Proxy-Authorization": f"Basic {credentials}"
}
proxies = {
"http": "http://proxy_host:port",
"https": "http://proxy_host:port",
}
response = requests.get(
"https://httpbin.org/ip",
proxies=proxies,
headers=headers,
timeout=10
)
महत्वपूर्ण: कुछ प्रॉक्सी प्रदाता प्रमाणीकरण को लॉगिन/पासवर्ड से नहीं, बल्कि विशेष स्थिर IP क्लाइंट (व्हाइटलिस्ट) से जोड़ते हैं। यदि आप IP बदलते हैं (उदाहरण के लिए, VPN के माध्यम से या प्रदाता के डायनामिक IP के माध्यम से), तो 407 त्रुटि सही क्रेडेंशियल्स के साथ भी उत्पन्न हो सकती है — क्योंकि आपका वर्तमान बाहरी IP प्रॉक्सी के पक्ष में व्हाइटलिस्ट में नहीं है। समाधान है प्रदाता के व्यक्तिगत खाते में लॉगिन करना और अनुमत IP की सूची को अपडेट करना, या IP-whitelist के बजाय लॉगिन/पासवर्ड प्रमाणीकरण पर स्विच करना।
Retry-लॉजिक और अपवाद प्रबंधन
व्यावहारिक रूप से प्रॉक्सी त्रुटियाँ कभी-कभी होती हैं — विशेष रूप से बड़े पैमाने पर पार्सिंग के दौरान। कोड की सही आर्किटेक्चर को प्रत्येक त्रुटि को अलग से लॉग करने और देरी के साथ पुनः प्रयास करने की योजना बनानी चाहिए।
import time
import requests
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def fetch_with_retry(url, proxies, max_retries=3, backoff=2):
for attempt in range(1, max_retries + 1):
try:
response = requests.get(url, proxies=proxies, timeout=15)
response.raise_for_status()
return response
except requests.exceptions.ProxyError as e:
logger.warning(f"[कोशिश {attempt}] ProxyError: {e}")
except requests.exceptions.SSLError as e:
logger.warning(f"[कोशिश {attempt}] SSLError: {e}")
except requests.exceptions.HTTPError as e:
if response.status_code == 407:
logger.error("407: लॉगिन/पासवर्ड या प्रॉक्सी के IP व्हाइटलिस्ट की जांच करें")
break
logger.warning(f"[कोशिश {attempt}] HTTPError: {e}")
except requests.exceptions.Timeout:
logger.warning(f"[कोशिश {attempt}] कनेक्शन टाइमआउट")
time.sleep(backoff * attempt)
raise RuntimeError(f"{url} को {max_retries} प्रयासों के बाद प्राप्त नहीं किया जा सका")
इस दृष्टिकोण से डिबगिंग के घंटों की बचत होती है: स्क्रिप्ट के पहले ही नेटवर्क ठहराव पर गिरने के बजाय, आपको प्रत्येक प्रयास पर त्रुटि के विशिष्ट प्रकार के साथ एक स्पष्ट लॉग मिलता है।
प्रॉक्सी का रोटेशन और बैन से निपटना
यदि ProxyError और 407 अक्सर कोड की सेटिंग्स से संबंधित होते हैं, तो बड़े पैमाने पर बैन और विशेष डोमेन पर स्थिर कनेक्शन अस्वीकृति लगभग हमेशा IP पूल की गुणवत्ता की समस्या को इंगित करती है। ऐसे कार्यों के लिए, जैसे मार्केटप्लेस (Wildberries, Ozon, Avito) को पार्स करना या सोशल मीडिया के साथ काम करना, प्रत्येक अनुरोध पर या निर्दिष्ट अंतराल के माध्यम से IP का रोटेशन करने की सिफारिश की जाती है।
import random
proxy_pool = [
"http://user:[email protected]:8000",
"http://user:[email protected]:8000",
"http://user:[email protected]:8000",
]
def get_random_proxy():
proxy = random.choice(proxy_pool)
return {"http": proxy, "https": proxy}
response = requests.get(url, proxies=get_random_proxy(), timeout=15)
प्रोडक्शन पार्सरों के लिए आमतौर पर प्रदाता की ओर से स्वचालित रोटेशन के साथ प्रॉक्सी लेना अधिक सुविधाजनक होता है — तब आपको IP की सूची को स्वयं रखने की आवश्यकता नहीं होती, रोटेशन एक एंडपॉइंट के माध्यम से पारदर्शी रूप से होता है। इस मामले में रेसिडेंशियल प्रॉक्सी रोटेशन के साथ विशेष रूप से अच्छी तरह से काम करते हैं ताकि एंटी-बॉट सुरक्षा को बायपास किया जा सके, जबकि डेटा सेंटर प्रॉक्सी एक अच्छा विकल्प है, यदि अनुरोधों की गति महत्वपूर्ण है और लक्षित वेबसाइट डेटा सेंटर रेंज को आक्रामक रूप से ब्लॉक नहीं करती है।
| प्रॉक्सी का प्रकार | गति | बैन का जोखिम | कार्य |
|---|---|---|---|
| डेटा सेंटर प्रॉक्सी | उच्च | मध्यम-उच्च | ओपन API की तेज़ पार्सिंग |
| रेसिडेंशियल प्रॉक्सी | मध्यम | कम | मार्केटप्लेस, सोशल मीडिया की पार्सिंग |
| मोबाइल प्रॉक्सी | मध्यम-निम्न | न्यूनतम | कठोर एंटी-बॉट सिस्टम के साथ काम करना |
Session, टाइमआउट और SSL सत्यापन
दीर्घकालिक स्क्रिप्टों (जैसे, चक्रीय पार्सरों) के लिए
requests.Session() का उपयोग करना चाहिए, बजाय अलग-अलग कॉल के
requests.get(). Session TCP कनेक्शनों को पुनः उपयोग करता है,
जो प्रॉक्सी सर्वर पर लोड को कम करता है और बड़े मात्रा में अनुरोधों पर ProxyError की संख्या को कम करता है।
session = requests.Session()
session.proxies.update({
"http": "http://user:password@proxy_host:port",
"https": "http://user:password@proxy_host:port",
})
for url in urls_list:
try:
resp = session.get(url, timeout=15)
print(resp.status_code, url)
except requests.exceptions.RequestException as e:
print(f"{url} पर त्रुटि: {e}")
अलग से verify पैरामीटर का उल्लेख करना महत्वपूर्ण है। यदि आप प्रॉक्सी के साथ काम कर रहे हैं,
जो स्वयं SSL प्रमाणपत्र को बदलता है (MITM-प्रॉक्सी डिबगिंग के लिए या कुछ कॉर्पोरेट प्रॉक्सी),
तो requests प्रमाणपत्र के असंगति पर शिकायत कर सकता है। सत्यापन को पूरी तरह से बंद करना
(verify=False) केवल परीक्षण वातावरण में करना चाहिए — प्रोडक्शन में
यह "मध्य में व्यक्ति" हमलों का जोखिम पैदा करता है:
# केवल स्थानीय डिबगिंग के लिए!
response = requests.get(url, proxies=proxies, verify=False, timeout=15)
# सही तरीका — प्रॉक्सी के लिए विश्वसनीय प्रमाणपत्र का पथ निर्दिष्ट करना
response = requests.get(url, proxies=proxies, verify="/path/to/proxy_cert.pem")
त्रुटियों का निदान चेक-लिस्ट
यदि स्क्रिप्ट प्रॉक्सी त्रुटि के साथ गिरती है, तो इस सूची के माध्यम से ऊपर से नीचे जाएँ — 90% मामलों में कारण पहले तीन बिंदुओं में मिलेगा।
- शब्दकोश में स्कीमा की जाँच करें
proxies— लगभग हमेशाhttp://होनी चाहिए, यहाँ तक कि HTTPS अनुरोधों के लिए। - कोड की ओर से समस्या को समाप्त करने के लिए सीधे
curl -xके माध्यम से प्रॉक्सी का परीक्षण करें। - सुनिश्चित करें कि लॉगिन और पासवर्ड में URL में अनएस्केप किए गए विशेष वर्ण नहीं हैं।
- जांचें कि क्या प्रॉक्सी विशेष IP (व्हाइटलिस्ट) से बंधी हुई है, न कि लॉगिन/पासवर्ड प्रमाणीकरण से।
- प्रॉक्सी को कार्य न करने के रूप में मानने से पहले
timeoutको 15-30 सेकंड तक बढ़ाएं। - यदि त्रुटि केवल किसी विशेष वेबसाइट पर उत्पन्न होती है — समस्या IP की प्रतिष्ठा में है, न कि कोड में।
- एकल प्रयासों के बजाय एक्सपोनेंशियल देरी के साथ पुनः प्रयास लॉजिक जोड़ें।
- बड़े पैमाने पर पार्सिंग करते समय एक स्थिर प्रॉक्सी के बजाय IP का रोटेशन करें।
निष्कर्ष
Python requests में अधिकांश प्रॉक्सी त्रुटियाँ तीन चीजों तक सीमित होती हैं: प्रॉक्सी URL में गलत स्कीमा
(http के बजाय https),
प्रमाणीकरण का अभाव या गलत प्रारूप, और IP पूल की गुणवत्ता। ProxyError आमतौर पर कनेक्शन समस्या या IP बैन के बारे में बताता है, SSLError WRONG_VERSION_NUMBER लगभग हमेशा प्रॉक्सी स्कीमा में गलती को इंगित करता है, और 407 —
लॉगिन/पासवर्ड या व्हाइटलिस्ट की समस्या।
यदि आप नियमित रूप से मार्केटप्लेस या सोशल मीडिया को पार्स करते समय बैन और 407 त्रुटियों का सामना करते हैं, तो आपको प्रॉक्सी के स्रोत पर पुनर्विचार करना चाहिए, न कि केवल कोड पर। स्थिर पार्सिंग के लिए कम बैन दर के साथ रेसिडेंशियल प्रॉक्सी का प्रयास करने की सिफारिश की जाती है — वे वास्तविक IP पते का उपयोग करते हैं और सुरक्षित वेबसाइटों पर ProxyError को काफी कम करते हैं। यदि प्राथमिकता गति और अनुरोधों की मात्रा है, न कि जटिल एंटी-बॉट सिस्टम को बायपास करना, तो डेटा सेंटर प्रॉक्सी पर विचार करें — वे सस्ते और सरल पार्सिंग कार्यों के लिए तेज़ होते हैं।