این همان تلهای است که هر توسعهدهنده اتوماسیون مرورگر دقیقاً یکبار در آن میافتد: --proxy-server=http://user:pass@host:port را به فلگهای راهاندازی Chrome اضافه میکنید، مرورگر خوب بالا میآید، و بعد هر صفحه روی یک پاپآپ احراز هویت که اسکریپتتان نه میبیند و نه میتواند کلیک کند، گیر میکند. Chrome بیسروصدا اطلاعات احراز هویت را از فلگ پروکسی حذف میکند. نه خطایی، نه خط لاگی، فقط یک دیالوگ مودال در مرورگری که هیچکس تماشایش نمیکند.
این راهنما نقشه کامل روشهای احراز هویت پروکسی است که واقعاً در Selenium و Playwright در سال ۲۰۲۶ کار میکنند — کدام را استفاده کنید، از کدام بپرهیزید، و کد دقیق هرکدام. (برای استراتژی انتخاب و چرخش پروکسی در این ابزارها، استفاده از پروکسی با Playwright و Puppeteer را ببینید — این مقاله صرفاً درباره عبور دادن اطلاعات احراز هویت است.)
کلاینتهای HTTP خط فرمان، اطلاعات احراز هویت را از روی URL پروکسی پارس میکنند و به 407 Proxy Authentication Required پروکسی بهصورت خودکار با یک هدر Proxy-Authorization پاسخ میدهند. Chromium این کار را نمیکند: --proxy-server فقط scheme://host:port را میپذیرد، و وقتی ۴۰۷ برمیگردد یک دیالوگ تعاملی نشان میدهد. در حالت headless حتی دیالوگی هم نیست — درخواست فقط شکست میخورد.
پس سؤال هیچوقت این نیست که «چطور رمز را در URL بگذارم» — سؤال این است که «کدام لایه بهجای من به ۴۰۷ پاسخ میدهد». چهار پاسخ کارا، بهترین اول.
Playwright این مشکل را درست حل کرد: خودش از طریق CDP به چالشهای احراز هویت پروکسی پاسخ میدهد. اطلاعات احراز هویت در آپشنهای launch یا context میروند:
# Python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(
proxy={
"server": "http://us.jibaoproxy.com:913",
"username": "USERNAME-session-job1",
"password": "PASSWORD",
}
)
// Node.js - و بهازای هر context، که قدرت اصلی همینجاست:
const browser = await chromium.launch({
proxy: { server: 'per-context' } // declare intent at launch
});
const ctx = await browser.newContext({
proxy: {
server: 'http://us.jibaoproxy.com:913',
username: 'USERNAME-session-job2',
password: 'PASSWORD',
}
});
پروکسی بهازای هر context یعنی یک پروسه مرورگر میتواند N کانتکست را روی N تای sticky session متفاوت اجرا کند — شالوده هر راهاندازی جدی اسکرپینگ با Playwright. اگر روی Playwright هستید، کارتان تمام است؛ به بخش تأیید بروید. هر چیزی پایینتر از این به این خاطر وجود دارد که Selenium معادلی ندارد.
selenium-wire دور Selenium یک پروکسی MITM محلی میپیچد که احراز هویت بالادست را مدیریت میکند:
from seleniumwire import webdriver # pip install selenium-wire
options = {
"proxy": {
"http": "http://USERNAME:[email protected]:913",
"https": "https://USERNAME:[email protected]:913",
}
}
driver = webdriver.Chrome(seleniumwire_options=options)
driver.get("https://example.com")
هشدارهایی که باید پیش از production بدانید:
رویکرد کلاسیک: یک افزونه کوچک تولیدشده که پروکسی را ست میکند و از طریق chrome.webRequest.onAuthRequired به احراز هویت پاسخ میدهد. نه MITM ای، نه پروسه اضافی، در Selenium ساده کار میکند:
import zipfile, json
HOST, PORT = "us.jibaoproxy.com", 913
USER, PASS = "USERNAME-session-sel1", "PASSWORD"
manifest = {
"version": "1.0.0", "manifest_version": 2, "name": "Proxy Auth",
"permissions": ["proxy", "webRequest", "webRequestBlocking", ""],
"background": {"scripts": ["background.js"]},
}
background = f"""
chrome.proxy.settings.set({{value: {{mode: "fixed_servers", rules: {{
singleProxy: {{scheme: "http", host: "{HOST}", port: {PORT}}}
}}}}, scope: "regular"}}, () => {{}});
chrome.webRequest.onAuthRequired.addListener(
() => ({{authCredentials: {{username: "{USER}", password: "{PASS}"}}}}),
{{urls: [""]}}, ["blocking"]
);
"""
with zipfile.ZipFile("proxy_auth.zip", "w") as zp:
zp.writestr("manifest.json", json.dumps(manifest))
zp.writestr("background.js", background)
from selenium import webdriver
opts = webdriver.ChromeOptions()
opts.add_extension("proxy_auth.zip")
driver = webdriver.Chrome(options=opts)
دو نکته ظریف: افزونهها در حالت headless کلاسیک بارگذاری نمیشوند — از --headless=new (Chrome 109+) استفاده کنید یا headed اجرا کنید؛ و اسکریپتهای background مربوط به Manifest V2 هنوز برای افزونههای اتوماسیون sideload شده کار میکنند اما حواستان به جدول زمانی منسوخ شدن MV2 در Chrome باشد — معادل MV3 به یک service worker و همان listener مربوط به onAuthRequired نیاز دارد.
یک پروکسی محلی کوچک اجرا کنید که اطلاعات احراز هویت را نگه دارد؛ مرورگر را بدون هیچ احراز هویتی به localhost اشاره دهید. با هر مرورگر، هر درایور، هر زبان، headless یا غیر آن کار میکند:
# با استفاده از pproxy (pip install pproxy) - ترمینال ۱:
pproxy -l http://127.0.0.1:8899 \
-r "http://USERNAME:[email protected]:913"
# اسکریپت شما - ترمینال ۲: Selenium ساده، بدون نیاز به احراز هویت
opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://127.0.0.1:8899")
driver = webdriver.Chrome(options=opts)
این تمیزترین پاسخ برای Firefox/geckodriver هم هست (جایی که ترفند افزونه کاربرد ندارد) و برای محیطهای خاص مثل تست اپلیکیشن Electron. هزینهاش: یک قطعه متحرک بیشتر برای نظارت، و مسیریابی بهازای هر context به یک پورت forwarder بهازای هر session نیاز دارد.
| روش | کار میکند در | Headless | session بهازای هر context | حکم production |
|---|---|---|---|---|
| بومی Playwright | Playwright | بله | بله | انتخاب پیشفرض |
| selenium-wire | Selenium (پایتون) | بله | بهازای هر driver | در مقیاس متوسط خوب است |
| افزونه احراز هویت | Selenium (هر زبان) | فقط --headless=new | بهازای هر driver | محکم، حواستان به MV3 |
| forwarder محلی | همه چیز | بله | یک پورت بهازای هر session | جایگزین جهانی |
بازگشت بیسروصدا به IP واقعی شما همان حالت شکستی است که حسابها را بن میکند. در ابتدای هر اجرا IP خروجی را assert کنید:
ip = driver.execute_script(
"return fetch('https://api.ipify.org').then(r => r.text())"
) if hasattr(driver, 'execute_script') else page.evaluate(
"fetch('https://api.ipify.org').then(r => r.text())"
)
assert ip != MY_REAL_IP, "Proxy not applied - aborting before we leak"
--proxy-server پاس دادید؛ Chrome حذفشان کرد. از یکی از چهار روش استفاده کنید.ERR_PROXY_CONNECTION_FAILED — host/port غلط یا عدم تطابق پروتکل. اول همان خط را با curl -x تست کنید؛ اگر curl کار کرد، مشکل از سیمکشی مرورگر شماست.--headless=new بروید.مرورگرها URL پروکسی به شکل user:pass@ را نمیخوانند — چیزی باید بهجای آنها به ۴۰۷ پاسخ دهد. در Playwright آن چیز توکار است؛ در Selenium آن چیز selenium-wire، یک افزونه احراز هویت تولیدشده، یا یک forwarder محلی است. بر اساس استک خودتان از جدول مقایسه انتخاب کنید، سپس در هر اجرا IP خروجی را assert کنید تا یک شکست احراز هویت بیسروصدا هرگز نتواند وسط کرال آدرس واقعی شما را لو دهد.
۵ دلار اعتبار مسکونی رایگان — یک گیتوی، sticky یا چرخشی، HTTP و SOCKS5.
شروع تست رایگانکاربران جدید با ثبتنام 500MB هدیه میگیرند، بهعلاوه بونوس اولین شارژ. پیشنهاد محدود.