Selenium Proxy Auth ve IP Rotasyonu: Eksiksiz Geliştirici Rehberi

Selenium ile kimlik doğrulamalı residential proxy'leri nasıl kullanacağınızı, parmak izi azaltma stratejilerini ve ölçekli paralel scraping için Grid + Docker mimarisini kod örnekleriyle öğrenin.

Selenium Proxy Auth ve IP Rotasyonu: Eksiksiz Geliştirici Rehberi

Selenium Proxy Auth Sorunu: Neden Standart Yöntemler Yetersiz Kalır?

Selenium, yıllardır web otomasyonunun belkemiği oldu. Ancak iş Selenium proxy auth konusuna gelince, çoğu mühendis duvara toslar. Standart Selenium WebDriver, user:pass formatındaki kimlik doğrulamalı proxy'leri doğal olarak desteklemez. ChromeOptions'a proxy adresi yazabilirsiniz ama kullanıcı adı ve şifreyi nereye koyacağınızı Selenium söylemez — çünkü Chromium'un kendisi HTTP proxy authentication'ı başlıkta iletir ve Selenium bu başlığı kontrol etmez.

Bu eksiklik, özellikle Selenium residential proxies kullanan scraping ve QA ekipleri için ciddi bir engeldir. Residential proxy sağlayıcıları neredeyse her zaman kimlik doğrulama gerektirir; datacenter proxy'ler bile artık token-based auth kullanıyor. Bu rehberde, bu sorunu beş farklı açıdan çözeceğiz: selenium-wire ile Chrome'da auth, Firefox profil bazlı proxy, parmak izi azaltma, dönen proxy havuzu ve konteyner tabanlı ölçekleme.

Chrome + selenium-wire: Kimlik Doğrulamalı Proxy'nin En Temiz Çözümü

selenium-wire, Selenium'un üzerinde ince bir katman olarak çalışır ve tüm HTTP trafiğini yakalayıp modifiye etmenize olanak tanır. En büyük avantajı: user:pass formatındaki proxy URL'lerini doğrudan kabul eder ve Selenium'un yapamadığını yapar — Proxy-Authorization başlığını otomatik ekler.

Kurulum ve Temel Kullanım

pip install selenium-wire selenium
from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options

# ProxyHat residential proxy — ülke hedefleme ile
PROXY_URL = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"

options = Options()
options.add_argument("--headless=new")
options.add_argument("--disable-gpu")
options.add_argument("--no-sandbox")

# selenium-wire, proxy'yi selenium_options yerine kendi config'inde alır
seleniumwire_options = {
    "proxy": {
        "http": PROXY_URL,
        "https": PROXY_URL,
        "no_proxy": "localhost,127.0.0.1",
    },
    "verify_ssl": False,
}

driver = webdriver.Chrome(
    options=options,
    seleniumwire_options=seleniumwire_options,
)

driver.get("https://httpbin.org/ip")
print(driver.page_source)
driver.quit()

Dikkat edilmesi gerekenler:

  • selenium-wire, trafiği bir yerel proxy üzerinden yönlendirir. Bu, ekstra bir katman anlamına gelir ve hafif gecikme ekler (genellikle <50ms).
  • Header manipulation için driver.requests nesnesine erişebilirsiniz — scraping sonrası analiz için paha biçilmez.
  • Sticky session istiyorsanız, kullanıcı adında session- bayrağını kullanın: user-country-US-session-abc123:PASSWORD.

Header ve İstek Müdahalesi

selenium-wire'ın gerçek gücü, isteklere müdahale edebilme yeteneğidir. Anti-bot sistemleri belli başlıkları kontrol eder — bunları interceptor ile değiştirebilirsiniz:

def interceptor(request):
    # Anti-fingerprint: şüpheli başlıkları kaldır
    del request.headers["sec-ch-ua"]
    del request.headers["sec-ch-ua-platform"]
    request.headers["Accept-Language"] = "en-US,en;q=0.9"

driver.request_interceptor = interceptor
driver.get("https://example.com")

Firefox: Profil Bazlı Proxy Yapılandırması

Firefox, Chrome'dan farklı olarak proxy ayarlarını doğrudan profil tercihlerinde (prefs) saklar. Bu, selenium-wire'a ihtiyaç duymadan kimlik doğrulamalı proxy kurmanın bir yoludur — ancak bir tuzağı vardır: Firefox da user:pass'ı proxy URL'sinden doğrudan almaz. Bunun yerine, bir proxy auto-config (PAC) dosyası veya yerleşik kimlik doğrulama mekanizması kullanmanız gerekir.

En pratik yöntem, Firefox profilinde proxy ayarlarını yapılandırmak ve kimlik doğrulamayı bir uzantı (extension) ile halletmektir:

from selenium import webdriver
from selenium.webdriver.firefox.options import Options
import zipfile, os, tempfile

# ProxyHat SOCKS5 — şehir hedefleme ile
PROXY_HOST = "gate.proxyhat.com"
PROXY_PORT = 1080
PROXY_USER = "user-country-DE-city-berlin"
PROXY_PASS = "PASSWORD"

def create_proxy_auth_extension(host, port, user, password):
    """Geçici bir Firefox uzantısı oluşturur ki proxy auth popup'ını otomatik doldursun."""
    manifest_json = """
    {
        "version": "1.0.0",
        "name": "Proxy Auth Helper",
        "manifest_version": 2,
        "background": {"scripts": ["background.js"]},
        "permissions": ["webRequest","webRequestBlocking","<all_urls>"]
    }
    """
    background_js = """
    var authCredentials = {
        username: '%s',
        password: '%s'
    };
    browser.webRequest.onAuthRequired.addListener(
        function(details) {
            return {authCredentials: authCredentials};
        },
        {urls: ["<all_urls>"]},
        ["blocking"]
    );
    """ % (user, password)

    tmp_dir = tempfile.mkdtemp()
    ext_path = os.path.join(tmp_dir, "proxy_auth.xpi")
    with zipfile.ZipFile(ext_path, "w") as zp:
        zp.writestr("manifest.json", manifest_json)
        zp.writestr("background.js", background_js)
    return ext_path

options = Options()
options.add_argument("--headless")
options.set_preference("network.proxy.type", 1)
options.set_preference("network.proxy.socks", PROXY_HOST)
options.set_preference("network.proxy.socks_port", PROXY_PORT)
options.set_preference("network.proxy.socks_remote_dns", True)

ext_path = create_proxy_auth_extension(
    PROXY_HOST, PROXY_PORT, PROXY_USER, PROXY_PASS
)
options.add_extension(ext_path)

driver = webdriver.Firefox(options=options)
driver.get("https://httpbin.org/ip")
print(driver.page_source)
driver.quit()

Bu yöntem, Firefox'un Manifest V2 uzantı API'sini kullanır. Mozilla'nın Manifest V3 geçişi nedeniyle, 2025 sonrasında bu kalıbı güncellemeniz gerekebilir — o zamana kadar declarativeNetRequest ile benzer bir yaklaşım mümkün olacaktır.

Selenium Stealth: Parmak İzini Azaltma Stratejileri

Proxy kullanmak IP tabanlı engellemeyi aşar ama bot tespit sistemleri IP'den çok daha fazlasına bakar. Selenium stealth teknikleri, WebDriver'ın otomasyon izlerini minimize eder. İki temel yaklaşım var: selenium-stealth kütüphanesi ve selenium-driverless (CDP-tabanlı).

selenium-stealth ile Temel Gizlenme

from selenium import webdriver
from selenium_stealth import stealth

options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option("useAutomationExtension", False)

driver = webdriver.Chrome(options=options)

stealth(driver,
    languages=["en-US", "en"],
    vendor="Google Inc.",
    platform="Win32",
    webgl_vendor="Intel Inc.",
    renderer="Intel Iris OpenGL Engine",
    fix_hairline=True,
)

# navigator.webdriver = true izini kaldır
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
})

driver.get("https://bot.sannysoft.com")
print("Stealth test sonuçlarını kontrol edin")
driver.quit()

selenium-driverless: Daha Derin Bir Yaklaşım

selenium-driverless, Chrome DevTools Protocol (CDP) üzerinden çalışır ve WebDriver'ın izlerini daha derin seviyede kaldırır. navigator.webdriver bayrağını CDP seviyesinde devre dışı bırakır, Runtime.enable izlerini temizler ve daha fazlası.

import asyncio
from selenium_driverless import webdriver as async_webdriver

async def main():
    options = async_webdriver.ChromeOptions()
    options.add_argument("--headless=new")

    driver = await async_webdriver.Chrome(options=options)
    await driver.get("https://nowsecure.nl")

    # CDP ile gelişmiş stealth
    await driver.execute_cdp_cmd("Network.setExtraHTTPHeaders", {
        "headers": {"Accept-Language": "en-US,en;q=0.9"}
    })

    page_source = await driver.page_source
    print(page_source[:500])
    await driver.quit()

asyncio.run(main())

Stealth hiyerarşisi: Basit siteler için selenium-stealth yeterlidir. Cloudflare Turnstile veya Datadome gibi ileri düzey korumalar için selenium-driverless veya doğrudan CDP kullanımı gerekir. Hiçbiri %100 geçiş garantisi vermez — sürekli güncellenen bir kedi-fare oyunudur.

Dönen Proxy Havuzu: Her Oturuma Yeni IP

Sabit bir proxy ile binlerce sayfa çekmek, IP'nin hızla bloklanmasına neden olur. Çözüm: her yeni WebDriver oturumuna farklı bir IP atayan bir rotating proxy pool deseni. ProxyHat'ın residential ağında, her yeni bağlantı zaten varsayılan olarak dönen IP alır — ama sticky session'lar ve ülke hedeflemesi ile kontrolü elinizde tutmak istersiniz.

Proxy Havuzu Yöneticisi

import itertools
from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options

# ProxyHat residential proxy havuzu — farklı lokasyonlar
PROXY_CREDENTIALS = [
    {"user": "user-country-US", "label": "US-East"},
    {"user": "user-country-DE", "label": "DE-Frankfurt"},
    {"user": "user-country-GB", "label": "GB-London"},
    {"user": "user-country-JP", "label": "JP-Tokyo"},
]
PROXY_PASS = "PASSWORD"
GATEWAY = "gate.proxyhat.com:8080"

def get_proxy_url(credential, session_id=None):
    """Oturum bazlı sticky veya dönen proxy URL'si oluşturur."""
    user = credential["user"]
    if session_id:
        user = f"{user}-session-{session_id}"
    return f"http://{user}:{PROXY_PASS}@{GATEWAY}"

def create_driver(proxy_url, headless=True):
    options = Options()
    if headless:
        options.add_argument("--headless=new")
    options.add_argument("--disable-gpu")
    options.add_argument("--no-sandbox")

    sw_options = {
        "proxy": {"http": proxy_url, "https": proxy_url},
        "verify_ssl": False,
    }
    return webdriver.Chrome(options=options, seleniumwire_options=sw_options)

class ProxyPool:
    def __init__(self, credentials):
        self._cycle = itertools.cycle(credentials)
        self._active_drivers = []

    def get_driver(self, session_id=None):
        cred = next(self._cycle)
        proxy_url = get_proxy_url(cred, session_id)
        driver = create_driver(proxy_url)
        self._active_drivers.append(driver)
        print(f"[Pool] {cred['label']} üzerinden bağlanıyor — session: {session_id or 'rotating'}")
        return driver

    def release(self, driver):
        driver.quit()
        if driver in self._active_drivers:
            self._active_drivers.remove(driver)

    def cleanup_all(self):
        for d in self._active_drivers[:]:
            d.quit()
        self._active_drivers.clear()

# Kullanım
pool = ProxyPool(PROXY_CREDENTIALS)
for i in range(8):
    driver = pool.get_driver(session_id=f"batch{i}")
    driver.get("https://httpbin.org/ip")
    print(f"Oturum {i}: {driver.find_element('tag name','body').text[:50]}")
    pool.release(driver)

Bu desen, itertools.cycle ile round-robin dağıtımı yapar. Üretimde, her proxy'nin başarı oranını takip edip ağırlıklı dağıtım (weighted round-robin) kullanmanız önerilir.

Selenium Grid + Docker: Paralel Scraping Ölçekleme

Tek bir makinede 5-10 WebDriver oturumu çalıştırmak mümkündür. Ama günde 100.000 sayfa çekmeniz gerektiğinde, Selenium Grid ve konteynerizasyon kaçınılmazdır.

Docker Compose ile Grid Kurulumu

# docker-compose.yml
version: '3.8'
services:
  selenium-hub:
    image: selenium/hub:4.18
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"
    environment:
      - SE_SESSION_REQUEST_TIMEOUT=300
      - SE_NODE_SESSION_TIMEOUT=300

  chrome-node:
    image: selenium/node-chrome:4.18
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=4
      - SE_NODE_OVERRIDE_MAX_SESSIONS=true
    deploy:
      replicas: 4
    shm_size: '2gb'

Grid üzerinde proxy kullanımı için, her node'un ChromeOptions'ına proxy ayarlarını enjekte etmeniz gerekir. selenium-wire Grid'de ekstra yapılandırma gerektirdiğinden, pratikte iki yaklaşım vardır:

  • Yaklaşım A: Her node'a özel bir Docker image oluşturun (selenium-wire yüklü) ve proxy'yi ortam değişkeni ile geçirin.
  • Yaklaşım B: Proxy'yi ağ seviyesinde yapılandırın — tüm node trafiğini bir SOCKS5 tüneli üzerinden yönlendirin. Bu, uygulama kodunu değiştirmez ama IP rotasyonu daha az esnek olur.

Grid Üzerinde Paralel Scraping

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from concurrent.futures import ThreadPoolExecutor, as_completed

HUB_URL = "http://localhost:4444/wd/hub"
PROXY_URL = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"

# NOT: Grid'de selenium-wire kullanılamadığından,
# proxy auth için Chrome uzantısı kullanılır

def create_proxy_auth_extension(proxy_url):
    from urllib.parse import urlparse
    parsed = urlparse(proxy_url)
    user = parsed.username
    password = parsed.password
    host = parsed.hostname
    port = parsed.port

    import zipfile, tempfile, os
    manifest = '{"version":"1.0","name":"proxy_auth","manifest_version":2,"permissions":["webRequest","webRequestBlocking","<all_urls>"],"background":{"scripts":["bg.js"]}}'
    bg_js = f'var c={{username:"{user}",password:"{password}"}};chrome.webRequest.onAuthRequired.addListener(function(d){{return{{authCredentials:c}}}},{{urls:["<all_urls>"]}},["blocking"]);'

    tmp = tempfile.mkdtemp()
    path = os.path.join(tmp, "ext.zip")
    with zipfile.ZipFile(path, "w") as z:
        z.writestr("manifest.json", manifest)
        z.writestr("bg.js", bg_js)
    return path

def scrape_page(url, proxy_url=PROXY_URL):
    options = Options()
    options.add_argument("--headless=new")
    options.add_argument("--no-sandbox")
    options.add_argument(f"--proxy-server=http://{urlparse(proxy_url).hostname}:{urlparse(proxy_url).port}")
    options.add_extension(create_proxy_auth_extension(proxy_url))

    driver = webdriver.Remote(
        command_executor=HUB_URL,
        options=options,
    )
    try:
        driver.get(url)
        return {"url": url, "title": driver.title, "status": "ok"}
    except Exception as e:
        return {"url": url, "error": str(e), "status": "fail"}
    finally:
        driver.quit()

URLS = ["https://httpbin.org/ip"] * 16  # test için

with ThreadPoolExecutor(max_workers=8) as executor:
    futures = {executor.submit(scrape_page, u): u for u in URLS}
    for f in as_completed(futures):
        result = f.result()
        print(f"{result['status'].upper()}: {result.get('title', result.get('error', ''))}")

Selenium vs Playwright: Hangi Durumda Hangisi?

Playwright, 2020'den beri hızla büyüyen bir alternatif. Selenium'un eksikliklerinin çoğunu giderir ama Selenium'un 20 yıllık ekosistem avantajı vardır. Somut bir karşılaştırma:

Kriter Selenium Playwright
Proxy Auth (user:pass) selenium-wire veya uzantı gerekir Doğal destek: proxy: {username, password}
Stealth / Anti-bot selenium-stealth, selenium-driverless eklentileri Daha temiz CDP entegrasyonu; daha az iz
Tarayıcı Desteği Chrome, Firefox, Edge, Safari (legacy) Chromium, Firefox, WebKit (tek API)
Paralel Çalıştırma Grid + Docker gerektirir Yerleşik browser.context() ile kolay
Ekosistem Olgunluğu Çok geniş: Appium, IDE eklentileri, CI entegrasyonları Büyüyor ama daha dar
Mevcut Kod Tabanı On binlerce proje, çok sayıda rehber Daha az referans, daha az StackOverflow cevabı
Ağ Müdahalesi selenium-wire ile mümkün route.intercept() ile doğal ve güçlü
Headless Mod Eski --headless ve yeni --headless=new ayrımı kafa karıştırır Tutarlı, varsayılan headless

Playwright'ı tercih edin eğer:

  • Yeni bir proje başlatıyorsanız ve proxy auth doğal destek istiyorsanız.
  • Ağ müdahalesi (request interception, mocking) yoğun kullanacaksanız.
  • Multi-browser testini tek API ile yapacaksanız.

Selenium'u tercih edin eğer:

  • Mevcut bir Selenium kod tabanınız var ve geçiş maliyeti yüksek.
  • Appium ile mobil test entegrasyonu gerekiyor.
  • Kurumsal CI/CD ortamlarında Grid zaten kurulu ve çalışıyor.
  • Selenium IDE ile kaydedilmiş testleriniz var.

Pratik tavsiye: Yeni scraping projeleri için Playwright'ı değerlendirin. Mevcut Selenium projeleri için, bu rehberdeki kalıpları uygulayarak proxy auth ve stealth sorunlarını çözebilirsiniz — tam yeniden yazma gerekmez.

Etik ve Hukuki Değerlendirme

Proxy ve otomasyon kullanırken bazı sınırları bilmek kritiktir:

  • robots.txt ve ToS: Bir sitenin hizmet şartları otomatik erişimi yasaklıyorsa, proxy kullanmak bu yasağı aşmaz — sadece tespiti zorlaştırır. Hukuki risk devam eder.
  • KVKK / GDPR: Kişisel veri toplayacaksanız, açık rıza gerekir. IP adresleri bile kişisel veri sayılabilir.
  • Orantılılık: Hedef sunucuya aşırı yük bindirmeyin. Rate limiting uygulayın — saniyede 5-10 istek, çoğu site için makul bir üst sınırdır.
  • Veri kullanımı: Topladığınız veriyi sadece belirttiğiniz amaçla kullanın. Rakip fiyatlarını izlemek genellikle meşrudur; kullanıcı profil verilerini izinsiz toplamak değildir.

Özet: Temel Çıkarımlar

Key Takeaways:

  • Selenium proxy auth için en pratik çözüm selenium-wire'dır — Chrome'da user:pass URL'sini doğrudan kabul eder.
  • Firefox'ta proxy auth, profil tercihleri + uzantı ile çözülür; selenium-wire'a gerek yoktur.
  • Selenium stealth için selenium-stealth temel, selenium-driverless ileri düzey korumalar içindir.
  • Dönen proxy havuzu deseni, her WebDriver oturumuna yeni IP atar ve IP bloklanmasını önler.
  • Paralel ölçekleme için Selenium Grid + Docker Compose en olgun yaklaşımdır; ancak Playwright'ın yerleşik paralel modeli daha basittir.
  • Yeni projelerde Playwright'ı değerlendirin; mevcut Selenium kod tabanları için bu rehberdeki kalıplar yeterlidir.

ProxyHat'ın residential proxy ağı, Selenium entegrasyonunuzun güvenilir omurgasıdır. 190+ ülkede IP havuzu, şehir seviyesi hedefleme ve oturum bazlı sticky session desteği ile scraping ve QA iş yükleriniz için uygun fiyatlı planlar mevcuttur. Detaylı lokasyon listesi için proxy lokasyonları sayfasını inceleyin. Web scraping kullanım senaryolarınız için web scraping kullanım örneği sayfamıza göz atın.

Başlamaya hazır mısınız?

148+ ülkede 50M+ konut IP'sine AI destekli filtreleme ile erişin.

Fiyatlandırmayı GörüntüleKonut Proxy'leri
← Bloga Dön