كل مكتبة HTTP في بايثون تأخذ البروكسي كرابط بالشكل scheme://user:pass@host:port؛ ما يختلف هو اسم المعامل، وما إذا كان يُعيّن لكل عميل أو لكل طلب، وكيفية التعامل مع SOCKS5 وDNS. المقتطفات أدناه هي الكود الدقيق الذي يعمل مع الإصدارات الحالية من requests وhttpx وaiohttp — تم تشغيل كل منها عبر بروكسي يتطلب مصادقة قبل نشر هذا المقال — متبوعة بالأشياء الثلاثة التي تسبب معظم أسئلة "البروكسي لا يعمل في بايثون": أسماء معاملات خاطئة منسوخة من دروس قديمة، ونقص الحزم الإضافية لـSOCKS، وبصمة TLS التي تكشف السكريبت بغض النظر عن عنوان IP.

رابط البروكسي

http://user:pass@proxy.example.com:8080     # بروكسي HTTP، يُستخدم لكل من أهداف http:// وhttps://
socks5://user:pass@proxy.example.com:1080   # SOCKS5، يتم حل DNS محليًا
socks5h://user:pass@proxy.example.com:1080  # SOCKS5، يتم حل DNS بواسطة البروكسي (استخدم هذا)

نقطتان تسببان المشاكل. أولاً، بروكسي HTTP يتعامل مع أهداف HTTPS أيضًا — يرسل العميل CONNECT وينشئ نفق TLS عبره — لذلك لا تحتاج أبدًا تقريبًا إلى مخطط https:// للبروكسي؛ فهذا يعني TLS إلى البروكسي نفسه، وهو ما لا يقدمه معظم المزودين. ثانيًا، إذا كان اسم المستخدم يحتوي على معاملات تدوير (user-country-de-session-abc123) أو كانت كلمة المرور تحتوي على @ أو : أو /، فقم بترميزها (urllib.parse.quote(pw, safe='')) وإلا فسيتم تحليل الرابط بشكل خاطئ.

requests

import requests

PROXY = "http://user:pass@proxy.example.com:8080"
proxies = {"http": PROXY, "https": PROXY}

# لكل طلب
r = requests.get("https://api.ipify.org?format=json", proxies=proxies, timeout=20)
print(r.json())

# لكل جلسة (يعيد استخدام الاتصالات؛ الطريقة المعتادة)
s = requests.Session()
s.proxies.update(proxies)
r = s.get("https://api.ipify.org?format=json", timeout=20)

القاموس يُفهرس حسب مخطط الهدف: الطلبات إلى عناوين http:// تستخدم إدخال "http"، والطلبات إلى https:// تستخدم "https". اضبط كلاهما على نفس البروكسي إلا إذا كان لديك سبب لعدم ذلك. دائمًا مرر timeout؛ فالبروكسي المعلق سيعلق سكريبتك إلى الأبد.

SOCKS5 يحتاج إلى الحزمة الإضافية: pip install "requests[socks]". ثم proxies = {"http": "socks5h://…", "https": "socks5h://…"}. بدون الحزمة ستحصل على InvalidSchema: Missing dependencies for SOCKS support.

متغيرات البيئة: requests يحترم HTTP_PROXY / HTTPS_PROXY / NO_PROXY افتراضيًا (trust_env=True). إذا كان البروكسي مستخدمًا بشكل غامض عندما لم تضبطه، أو غير مستخدم عندما ضبطته، تحقق من البيئة.

httpx

import httpx

PROXY = "http://user:pass@proxy.example.com:8080"

# متزامن
with httpx.Client(proxy=PROXY, timeout=20) as client:
    r = client.get("https://api.ipify.org?format=json")
    print(r.json())

# غير متزامن
import asyncio
async def main():
    async with httpx.AsyncClient(proxy=PROXY, timeout=20) as client:
        r = await client.get("https://api.ipify.org?format=json")
        print(r.json())
asyncio.run(main())

المعامل هو proxy= (مفرد). الدروس القديمة تعرض proxies={"http://": …, "https://": …}؛ هذه الكلمة الرئيسية أُهملت في httpx 0.26 وأُزيلت في 0.28، وتمريرها الآن يرفع TypeError: Client.__init__() got an unexpected keyword argument 'proxies'. إذا كنت بحاجة إلى بروكسيات مختلفة لأهداف مختلفة، استخدم mounts:

mounts = {
    "https://api.example.com": httpx.HTTPTransport(proxy="http://user:pass@dc-proxy:8080"),
    "all://": httpx.HTTPTransport(proxy="http://user:pass@resi-proxy:8080"),
}
client = httpx.Client(mounts=mounts)

SOCKS5: pip install "httpx[socks]"، ثم proxy="socks5://…". httpx يحل أسماء المضيفين عبر بروكسي SOCKS افتراضيًا. HTTP/2: pip install "httpx[http2]" وhttpx.Client(http2=True, …) — هذا مهم لأن المتصفح عبر البروكسي يكون على HTTP/2 على أي حال (انظر HTTP/2 وHTTP/3 عبر البروكسيات).

aiohttp

import aiohttp, asyncio

PROXY = "http://user:pass@proxy.example.com:8080"

async def main():
    async with aiohttp.ClientSession() as session:
        async with session.get("https://api.ipify.org?format=json",
                               proxy=PROXY,
                               timeout=aiohttp.ClientTimeout(total=20)) as r:
            print(await r.json())

asyncio.run(main())

يُمرر البروكسي لكل طلب (أو يُضبط مرة واحدة عبر موصل مخصص). تُوضع بيانات الاعتماد في الرابط؛ صيغة proxy_auth=aiohttp.BasicAuth(...) المنفصلة لا تزال تعمل في 3.x لكنها مهملة اعتبارًا من 3.14 ومقرر إزالتها في 4.0، لذا يفضل استخدام صيغة الرابط. aiohttp لا يقرأ متغيرات البيئة HTTP_PROXY إلا إذا أنشأت الجلسة مع trust_env=True. aiohttp الأصلي يتحدث بروتوكول HTTP فقط؛ لـSOCKS استخدم حزمة aiohttp-socks وProxyConnector الخاص بها.

تدوير البروكسيات: نمط معرف الجلسة

مع بوابة backconnect (انظر كيف تعمل بوابات التدوير) نادرًا ما تدور في بايثون نفسها — بل تدور عن طريق تغيير اسم المستخدم. معرف جلسة جديد يعني عنوان IP خروج جديد؛ ومعرف مُعاد استخدامه يحافظ عليه:

import secrets, requests

def proxy_for(session_id: str, country: str = "de") -> dict:
    user = f"customer-country-{country}-session-{session_id}"   # تنسيق خاص بالمزود
    url  = f"http://{user}:PASSWORD@gate.provider.com:7777"
    return {"http": url, "https": url}

# ثابت: نفس IP لتدفق متعدد الخطوات
sid = secrets.token_hex(4)
s = requests.Session(); s.proxies.update(proxy_for(sid))
s.get("https://shop.example/login"); s.post("https://shop.example/cart", data=...)

# تدوير: IP جديد لكل عنصر
for url in urls:
    requests.get(url, proxies=proxy_for(secrets.token_hex(4)), timeout=20)

قم بالتدوير عند الفشل أيضًا: التقط 403/429 وعلامة CAPTCHA، وأعد المحاولة بمعرف جلسة جديد وملف تعريف ارتباط جديد — نفس IP مع نفس ملفات الارتباط هو نفس الزائر.

الخطأ الذي لا يصلحه أي بروكسي: بصمة TLS

جميع المكتبات الثلاث تنشئ اتصالات TLS عبر وحدة ssl في بايثون (OpenSSL). تقوم أنظمة مكافحة البوتات ببصمة هذا المصافحة وتعرف أنه ليس متصفحًا، مهما ضبطت User-Agent. خلف عنوان IP سكني مثالي، لا يزال السكريبت يُعرف كسكريبت — الآلية موضحة في شرح بصمة TLS. للأهداف المحمية، انتقل إلى عميل يحاكي المتصفح؛ curl_cffi يحافظ على واجهة برمجة مشابهة لـrequests:

# pip install curl_cffi
from curl_cffi import requests as cffi_requests

r = cffi_requests.get("https://protected.example/",
                      impersonate="chrome",                 # يعيد إنتاج بصمة TLS وHTTP/2 الخاصة بـChrome
                      proxies={"https": "http://user:pass@proxy.example.com:8080"},
                      timeout=20)

ثم حافظ على بقية القصة متسقة — User-Agent خاص بـChrome، وتلميحات sec-ch-ua المطابقة، وAccept-Language معقول لبلد البروكسي. للمواقع التي تتطلب أيضًا تحديات JavaScript، لا يكفي أي عميل HTTP؛ استخدم متصفحًا حقيقيًا كما في البروكسيات في Playwright وPuppeteer وSelenium.

الأخطاء ومعانيها

الخطأالمعنىالحل
ProxyError … 407 Proxy Authentication Requiredبيانات اعتماد خاطئة، أو عنوان IP الخاص بك غير مدرج في القائمة البيضاءتحقق من اسم المستخدم/كلمة المرور (سلاسل التدوير الطويلة!)، قم بترميز الأحرف الخاصة، تحقق من القائمة البيضاء
InvalidSchema: Missing dependencies for SOCKS supportrequests بدون حزمة socks الإضافيةpip install "requests[socks]"
TypeError: … unexpected keyword argument 'proxies'httpx ≥ 0.28 مع معامل محذوفاستخدم proxy= أو mounts=
ProxyError … Cannot connect to proxy / ConnectTimeoutمضيف/منفذ خاطئ، أو البروكسي معطل، أو جدار حمايةتحقق باستخدام curl -x؛ جرب البروتوكول الآخر
عنوان IP حقيقي من نقطة نهاية صدى IPالبروكسي لم يُطبق (مفتاح قاموس خاطئ، تجاوز متغير بيئة، معامل لكل طلب مفقود في aiohttp)اطبع session.proxies؛ تحقق من trust_env؛ مرر proxy= في الطلب
SSLError فقط عبر البروكسيالبروكسي يعترض TLS (MITM) أو مخطط خاطئاستخدم مخطط http:// للبروكسي؛ اسأل المزود عما إذا كان ينهي TLS
403/CAPTCHA على مواقع محمية، IP يبدو جيدًابصمة TLS/HTTP تكشف بايثونcurl_cffi مع impersonate، أو متصفح حقيقي
يعمل لفترة ثم 429تم الوصول إلى حد معدل لكل IPقم بتدوير معرف الجلسة؛ أبطئ؛ راجع دليل التدوير

قالب صحيح وموجز

import requests, secrets
from urllib.parse import quote

GATE, PORT = "gate.provider.com", 7777
USER_BASE, PASS = "customer-country-de", quote("p@ss:word", safe="")

def make_session() -> requests.Session:
    sid = secrets.token_hex(4)
    url = f"http://{USER_BASE}-session-{sid}:{PASS}@{GATE}:{PORT}"
    s = requests.Session()
    s.proxies.update({"http": url, "https": url})
    s.headers.update({"User-Agent": "python-requests"})   # UA صادق للأهداف المتسامحة
    return s

s = make_session()
r = s.get("https://api.ipify.org?format=json", timeout=20)
r.raise_for_status()
print(r.json())

تحقق من تغير IP، ثم ابنِ عليه. لفحص شامل قبل التشغيل (تسريبات، ترويسات، قوائم حظر) انظر كيف تختبر بروكسي؛ لاختيار بين سكني ومركز بيانات لهدف معين، مقارنة أنواع البروكسيات.

الأسئلة الشائعة

كيف أستخدم بروكسي مع Python requests؟

مرر proxies={"http": url, "https": url} إلى الطلب أو اضبطه على Session، حيث url هو http://user:pass@host:port. أضف timeout=. لـSOCKS5 قم بتثبيت requests[socks] واستخدم socks5h://.

لماذا يقول httpx 'unexpected keyword argument proxies'؟

لأن proxies= أُزيل في httpx 0.28. استخدم proxy="http://…" لبروكسي واحد، أو mounts= لبروكسيات لكل هدف.

كيف أضبط بروكسي في aiohttp؟

مرر proxy="http://user:pass@host:port" لكل طلب (session.get(url, proxy=…)). معامل proxy_auth= مهمل؛ ضع بيانات الاعتماد في الرابط. استخدم aiohttp-socks لـSOCKS.

كيف أدور البروكسيات في بايثون؟

مع مزود backconnect، غيّر معرف الجلسة في اسم مستخدم البروكسي لكل طلب أو لكل تدفق — لا حاجة لقائمة IP. قم بالتدوير عند 403/429 واقرن كل IP جديد بملف تعريف ارتباط جديد.

لماذا يُحظر سكريبتي بينما متصفحي على نفس البروكسي لا يُحظر؟

بصمة TLS وHTTP/2: وحدة ssl في بايثون لا تبدو كمتصفح. استخدم curl_cffi مع impersonate= أو أتمتة متصفحًا حقيقيًا.

هل أستخدم socks5 أم socks5h؟

socks5h. الحرف h يجعل البروكسي يحل أسماء المضيفين، مما يمنع تسرب DNS ويسمح لك بالوصول إلى مضيفين لا يمكن حلها إلا بواسطة البروكسي.