جميع أطر أتمتة المتصفحات تقبل البروكسي كخيار عند الإطلاق، لكن البروكسيات الموثقة تتطلب معالجة خاصة لأن Chromium لا يقبل user:pass@ في عنوان البروكسي: يأخذ Playwright بيانات الاعتماد كحقول منفصلة (ويمكنه تعيين بروكسي مختلف لكل سياق متصفح)، ويحتاج Puppeteer إلى page.authenticate()، بينما يحتاج Selenium إلى إضافة أو مُوجّه محلي. يقدم هذا الدليل أكوادًا عملية لكل إطار، ثم يغطي الجزء الأهم من الصيغة: المتصفح بدون واجهة رسومية خلف عنوان IP سكني لا يزال قابلاً للتمييز ما لم تتطابق بقية خصائصه.

الحقيقة الأساسية التي تشكل كل شيء: Chromium يتجاهل بيانات اعتماد البروكسي في عنوان URL

الأدوات سطر الأوامر ومكتبات بايثون تقبل بسهولة http://user:pass@host:port. بينما يأخذ Chromium عبر العلم --proxy-server فقط host:port (مع مخطط اختياري)؛ ويتم إسقاط بيانات الاعتماد فيه بصمت. عندما يرد البروكسي برمز 407، يعرض المتصفح نافذة مصادقة — لا يراقبها أي سكربت أتمتة. لذلك لكل إطار طريقته الخاصة في توفير اسم المستخدم وكلمة المرور، وهنا تأتي معظم مشاكل "البروكسي يعمل في curl لكن ليس في سكربت المتصفح الخاص بي". فايرفوكس أكثر تسامحًا في بعض المسارات، لكن الآليات الخاصة بالإطارات أدناه تعمل عبر المحركات.

Playwright

يتمتع Playwright بدعم بروكسي من الدرجة الأولى مع حقول بيانات اعتماد منفصلة، والميزة التي تجعله الأنسب للعمل متعدد الهويات — يمكن تعيين البروكسي لكل سياق متصفح، بحيث يمكن لعملية متصفح واحدة استضافة عدة جلسات معزولة، تخرج كل منها من عنوان IP مختلف.

بايثون

from playwright.sync_api import sync_playwright

PROXY = {"server": "http://proxy.example.com:8080",
         "username": "user", "password": "pass"}

with sync_playwright() as p:
    # الخيار أ: بروكسي واحد للمتصفح بأكمله
    browser = p.chromium.launch(proxy=PROXY)
    page = browser.new_page()
    page.goto("https://api.ipify.org?format=json")
    print(page.text_content("body"))
    browser.close()

    # الخيار ب: بروكسي مختلف لكل سياق (متصفح واحد، هويات متعددة)
    browser = p.chromium.launch(proxy={"server": "per-context"})   # placeholder; real proxies come from contexts
    ctx_de = browser.new_context(proxy={"server": "http://gate.provider.com:7777",
                                        "username": "customer-country-de-session-a1", "password": "pass"},
                                 locale="de-DE", timezone_id="Europe/Berlin")
    ctx_us = browser.new_context(proxy={"server": "http://gate.provider.com:7777",
                                        "username": "customer-country-us-session-b2", "password": "pass"},
                                 locale="en-US", timezone_id="America/New_York")
    for ctx in (ctx_de, ctx_us):
        pg = ctx.new_page(); pg.goto("https://api.ipify.org?format=json"); print(pg.text_content("body"))
    browser.close()

تفصيلان. تتطلب البروكسيات لكل سياق في Chromium أن يتم إطلاق المتصفح مع خيار بروكسي (أي قيمة — العنصر النائب الموثق هو {"server": "per-context"})؛ وبدونه لا يمكن للسياقات تجاوز ذلك. ولاحظ تعيين locale وtimezone_id بجانب البروكسي: عنوان IP ألماني مع منطقة زمنية أمريكية هو تناقض تزنه أنظمة مكافحة البوتات، كما هو موضح في كيف تعمل أنظمة مكافحة البوتات. البروكسيات SOCKS5 مدعومة ("server": "socks5://host:1080") لكن Chromium لا يرسل بيانات الاعتماد إلى بروكسيات SOCKS، لذا استخدم مصادقة القائمة البيضاء للعناوين مع SOCKS.

Node.js

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ proxy: { server: 'per-context' } });
  const context = await browser.newContext({
    proxy: { server: 'http://gate.provider.com:7777',
             username: 'customer-country-de-session-a1', password: 'pass' },
    locale: 'de-DE', timezoneId: 'Europe/Berlin',
  });
  const page = await context.newPage();
  await page.goto('https://api.ipify.org?format=json');
  console.log(await page.textContent('body'));
  await browser.close();
})();

حقل bypass في Playwright ("bypass": "localhost,*.internal") يستثني المضيفين من البروكسي، وlaunch_persistent_context() يقبل نفس خيار proxy إذا كنت بحاجة إلى ملف تعريف دائم.

Puppeteer

يمرر Puppeteer البروكسي كعلم لـ Chromium ويصادق لكل صفحة:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    args: ['--proxy-server=http://proxy.example.com:8080'],
  });
  const page = await browser.newPage();
  await page.authenticate({ username: 'user', password: 'pass' });   // answers the 407 for this page
  await page.goto('https://api.ipify.org?format=json');
  console.log(await page.evaluate(() => document.body.innerText));
  await browser.close();
})();

يجب استدعاء page.authenticate() قبل التنقل وعلى كل صفحة (تبويب) ستستخدم البروكسي. البروكسي على مستوى المتصفح — لا يمتلك Puppeteer إعداد بروكسي لكل سياق كما في Playwright. للهويات المتعددة لديك ثلاثة خيارات: تشغيل عدة عمليات متصفح (بروكسي واحد لكل منها؛ ثقيل لكن بسيط)، أو استخدام --proxy-server يشير إلى بروكسي تحويل محلي يوجّه بناءً على علامة معينة، أو الانتقال إلى Playwright. مفيد أيضًا: --proxy-bypass-list=<-loopback> إذا كنت بحاجة إلى بروكسي لـ localhost أيضًا، وpuppeteer-extra مع إضافة البروكسي الخاصة به، والتي تتعامل مع المصادقة ويمكنها التبديل لكل صفحة.

Selenium

يضبط Selenium البروكسي من خلال خيارات المتصفح. البروكسيات غير الموثقة (القائمة البيضاء للعناوين) سطر واحد؛ أما الموثقة فهي الحالة الصعبة.

Chrome، مصادقة القائمة البيضاء

from selenium import webdriver

opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://proxy.example.com:8080")
driver = webdriver.Chrome(options=opts)
driver.get("https://api.ipify.org?format=json")
print(driver.find_element("tag name", "body").text)
driver.quit()

Chrome، اسم المستخدم/كلمة المرور

لا يحتوي بروتوكول WebDriver الخاص بـ Selenium على خطاف للرد على 407 من البروكسي. الحلول البديلة القياسية:

  1. Selenium Wire (بايثون): إضافة لـ Selenium توجّه حركة المرور عبر بروكسي محلي خاص بها وتدعم الوكلاء الموثقين:
    from seleniumwire import webdriver   # pip install selenium-wire
    opts = {"proxy": {"http": "http://user:pass@proxy.example.com:8080",
                      "https": "http://user:pass@proxy.example.com:8080"}}
    driver = webdriver.Chrome(seleniumwire_options=opts)
    لاحظ أن Selenium Wire لم يعد صيانته نشطة؛ لا يزال يعمل مع Chrome الحالي لدى الكثيرين، لكن اعتبره حلاً مؤقتًا.
  2. إضافة Chrome مولّدة تضبط البروكسي عبر chrome.proxy وترد على onAuthRequired ببيانات الاعتماد — نمط معروف؛ الإضافة عبارة عن manifest وبضعة أسطر من سكربت الخلفية، تُحمَّل بـ opts.add_extension(...). لا تعمل في الوضع بدون واجهة رسومية مع Chrome الأقدم (الإضافات غير مدعومة هناك)؛ تعمل في headless=new الحالي.
  3. بروكسي تحويل محلي على 127.0.0.1 يحمل بيانات الاعتماد ويوجّه إلى الأعلى؛ وجّه Chrome إليه بدون مصادقة. مستقل عن الإطار ومتين.
  4. مصادقة القائمة البيضاء من المزود، إذا كان جهازك لديه عنوان IP ثابت — يتجاوز المشكلة تمامًا.

Firefox

opts = webdriver.FirefoxOptions()
opts.set_preference("network.proxy.type", 1)
opts.set_preference("network.proxy.http", "proxy.example.com");  opts.set_preference("network.proxy.http_port", 8080)
opts.set_preference("network.proxy.ssl",  "proxy.example.com");  opts.set_preference("network.proxy.ssl_port", 8080)
opts.set_preference("network.proxy.socks_remote_dns", True)     # remote DNS if using SOCKS
driver = webdriver.Firefox(options=opts)

سيظل Firefox يعرض نافذة مصادقة للبروكسيات التي تتطلب اسم مستخدم/كلمة مرور؛ تنطبق طرق المُوجّه المحلي أو القائمة البيضاء.

ما لا يصلحه البروكسي في المتصفح بدون واجهة رسومية

المتصفح الحقيقي يتجاوز بصمة TLS وHTTP/2 — المصافحة هي بالفعل من Chrome (انظر بصمة TLS). لكنه لا يتجاوز بمفرده طبقة JavaScript:

  • navigator.webdriver يكون true تحت الأتمتة؛ تفحصه المواقع أولاً.
  • الوضع بدون واجهة رسومية له اختلافات في العرض وAPI (إضافات مفقودة، سلاسل محددة لمُصيِّر WebGL، أبعاد نافذة) تختبرها سكربتات البصمة. الوضع الأحدث لـ Chrome (headless=new) أقرب بكثير إلى الوضع بواجهة لكن ليس مطابقًا.
  • WebRTC يمكن أن يكشف عنوان IP الحقيقي للجهاز ما لم يُعطَّل أو يُزيَّف؛ لا يلمسه البروكسي. اختبره — كيف تختبر بروكسيًا.
  • المنطقة الزمنية واللغة والموقع الجغرافي تأتي من الجهاز ما لم تضبطها (في Playwright: timezone_id، locale، geolocation)؛ عدم تطابقها مع بلد البروكسي هو مؤشر كلاسيكي.
  • السلوك: تنقلات فورية، بدون حركة ماوس، توقيت متطابق في كل تشغيل.

إضافات التخفي (puppeteer-extra-plugin-stealth، playwright-stealth) تصحح أبرز الآثار؛ متصفحات مكافحة الكشف تذهب أبعد بتوفير بصمة متماسكة لكل ملف تعريف وكشف منفذ تصحيح يتصل به سكربت Playwright/Puppeteer الخاص بك — وهو الحل الإنتاجي للعمل على الحسابات. انظر ما هو متصفح مكافحة الكشف، ولاختيار نوع IP خلف كل ملف تعريف، تصنيفنا للبروكسيات لمتصفحات مكافحة الكشف.

اختيار الإطار المناسب للعمل مع البروكسيات

PlaywrightPuppeteerSelenium
بروكسي موثقدعم أصلي (حقول username/password)page.authenticate() لكل صفحةيتطلب حلًا بديلاً (Wire، إضافة، مُوجّه محلي)
بروكسي مختلف لكل جلسةلكل سياق، متصفح واحدمتصفح واحد لكل بروكسيمتصفح واحد لكل بروكسي
SOCKS5نعم (بدون بيانات اعتماد ← قائمة بيضاء)عبر العلم (بدون بيانات اعتماد)عبر الخيارات/التفضيلات
اللغة / المنطقة الزمنية لكل جلسةخيارات سياق أصليةواجهات برمجة المحاكاة / الأعلامالتفضيلات / CDP
الأنسب لـالكشط والاختبار متعدد الهوياتأتمتة Chrome مركزية على Nodeمجموعات قديمة، شبكات متصفحات متعددة

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

كيف أستخدم بروكسيًا موثقًا في Playwright؟

مرر proxy={"server": "http://host:port", "username": "…", "password": "…"} إلى launch() أو، لكل سياق، إلى new_context() (أطلق أولاً بـ proxy={"server": "per-context"}).

كيف أستخدم بروكسيًا مع مصادقة في Puppeteer؟

أطلق بـ args: ['--proxy-server=host:port'] واستدعِ await page.authenticate({username, password}) قبل page.goto() في كل صفحة.

لماذا يتجاهل Chrome user:pass@ في --proxy-server؟

علم Chromium يقبل فقط scheme://host:port؛ لا تُحلل بيانات الاعتماد. يرد على 407 من البروكسي بنافذة تفاعلية، لذا يجب على الأتمتة توفير بيانات الاعتماد عبر آلية الإطار بدلاً من ذلك.

هل يمكنني استخدام بروكسي مختلف لكل تبويب؟

ليس لكل تبويب. يقوم Playwright بذلك لكل سياق متصفح (كل سياق جلسة معزولة)؛ يحتاج Puppeteer وSelenium إلى مثيل متصفح واحد لكل بروكسي، أو بروكسي تحويل محلي.

هل يجعل البروكسي Chrome بدون واجهة رسومية غير قابل للكشف؟

لا. يصلح طبقة IP، وباعتباره متصفحًا حقيقيًا، طبقة TLS. أعلام الأتمتة، وآثار الوضع بدون واجهة، وWebRTC، وعدم تطابق المنطقة الزمنية، والسلوك كلها إشارات منفصلة تحتاج معالجة منفصلة.

هل يجب أن يكون البروكسي سكنيًا أم من مركز بيانات لأتمتة المتصفح؟

أيًا كان ما تتطلبه سياسة IP الخاصة بالموقع المستهدف — المتصفح لا يغير هذه المعادلة. مركز البيانات حيث يُسمح به؛ سكني أو جوال في المواقع المحمية؛ ثابت (ISP) للملفات الشخصية المسجلة الدخول بشكل دائم. انظر مقارنة أنواع البروكسيات.