Puppeteer-Extra Stealth Plugin ve Proxy: Tam Kapsamlı Anti-Tespit Rehberi

Raw Puppeteer neden tespit edilir, puppeteer-extra stealth plugin hangi sinyalleri yamar ve yerel proxy'lerle birleştiğinde nasıl sömürülemez bir yığın oluşturur? Node.js kazıma mühendisleri için kod odaklı rehber.

Puppeteer-Extra Stealth Plugin ve Proxy: Tam Kapsamlı Anti-Tespit Rehberi

Neden Raw Puppeteer Tespit Edilir?

Puppeteer, Chromium'un DevTools Protocol üzerinden otomasyon yapmak için tasarlanmış güçlü bir kütüphanedir — ama tarayıcı parmak izi endüstrisi onu yakalamak için tasarlanmıştır. İlk puppeteer.launch() çağrınızdan itibaren en az üç bariz sinyal sızdırılır:

  • navigator.webdriver — W3C standardı gereği otomasyon flag'i true olarak ayarlanır. Basit bir navigator.webdriver kontrolü botunuzu anında ele verir.
  • Plugins dizisi tutarsızlığı — Otomatikleştirilmiş Chromium, normal kullanıcı profillerinden farklı bir navigator.plugins dizisi sunar. Uzantı sayısı ve MIME type haritası fingerprint veritabanlarında kataloglanmıştır.
  • iframe chromedriver eserleri — ChromeDriver, bazı sayfa yüklemelerinde cdc_ önekli gizli iframe'ler enjekte eder. Cloudflare ve DataDome bu iframe'leri tarar.

Bunlar sadece buzdağının görünen kısmı. WebGL render parametreleri, canvas hash sapmaları, window.chrome nesnesinin eksikliği, Permissions.query davranış farklılıkları — hepsi otomasyonu ele verir. Tek bir sinyal bile engellenmeye neden olabilir; onlarca sinyal bir araya geldiğinde ise başarısızlık kaçınılmazdır.

Puppeteer-Extra Stealth Plugin: Hangi Sinyalleri Yamar?

puppeteer-extra, Puppeteer'ı eklenti mimarisiyle genişleten bir sarmalayıcıdır. En popüler eklentisi olan puppeteer-extra-plugin-stealth, dokuz alt modülle fingerprint sızıntılarını sistematik olarak kapatır:

Stealth Alt ModülüPatch Edilen SinyalMekanizma
evasions/navigator.webdrivernavigator.webdriver === trueProperty'yi undefined yapar
evasions/navigator.pluginsBozuk plugins dizisiGerçekçi plugin listesi enjekte eder
evasions/navigator.languagesEksik dil tercihleriTutarlı Accept-Language başlığı sağlar
evasions/webgl.vendorHeadless GPU bilgisiVendor/renderer string'lerini değiştirir
evasions/iframe.contentWindowChromeDriver iframe eserlericdc_ iframe'lerini kaldırır
evasions/media.codecsHeadless codec desteğiMediaSource yeteneklerini simüle eder
evasions/user-agent-overrideHeadless UA string'iHeadless ibaresini kaldırır
evasions/console.debugDevTools debug sızıntısıDebug çağrılarını sessize alır
evasions/stack-traceOtomasyon kaynaklı stack traceStack trace'leri temizler

Kurulum ve temel kullanım son derece basittir:

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

puppeteer.use(StealthPlugin());

(async () => {
  const browser = await puppeteer.launch({
    headless: 'new',
    args: ['--no-sandbox', '--disable-setuid-sandbox']
  });

  const page = await browser.newPage();
  await page.goto('https://bot.sannysoft.com/');

  // Tüm stealth patch'lerin aktif olduğunu doğrula
  const isWebdriver = await page.evaluate(() => navigator.webdriver);
  console.log('navigator.webdriver:', isWebdriver); // undefined

  await browser.close();
})();

Stealth plugin tek başına güçlüdür — ama IP bazlı engellemeler karşısında çaresizdir. Bir sonraki adım, parmak izi yamalarını IP rotasyonuyla birleştirmektir.

Stealth + Yerel Proxy: En Güçlü Anti-Tespit Yığını

Parmak izi yamaları tarayıcı kimliğinizi gizlerken, yerel proxy'ler ağ kimliğinizi gizler. Veri merkezi IP'leri ASN veritabanlarında kataloglanmış olduğundan, Cloudflare ve benzeri WAF'lar bu IP'leri anında bayraklar. Yerel proxy'ler ise gerçek ISP bağlantılarından gelen IP'ler sunar — bu da trafiğinizi normal kullanıcı trafiğinden ayırt edilemez kılar.

ProxyHat yerel proxy'lerini Puppeteer ile entegre etmek için --proxy-server Chrome bayrağını kullanın:

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

puppeteer.use(StealthPlugin());

(async () => {
  const browser = await puppeteer.launch({
    headless: 'new',
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
      `--proxy-server=http://gate.proxyhat.com:8080`
    ]
  });

  const page = await browser.newPage();

  // ProxyHat kimlik doğrulaması
  await page.authenticate({
    username: 'user-country-US',
    password: 'PASSWORD'
  });

  await page.goto('https://httpbin.org/ip');
  const ip = await page.evaluate(() =>
    document.querySelector('pre').innerText
  );
  console.log('Yerel IP:', ip);

  await browser.close();
})();

Bu yapılandırma ile her sayfa yüklemesi ABD tabanlı bir yerel IP üzerinden gerçekleşir. Ülke hedeflemesini değiştirmek için kullanıcı adı içindeki country parametresini değiştirmeniz yeterlidir: user-country-DE, user-country-JP vb.

SOCKS5 ile Daha Derin Gizlilik

HTTP proxy'ler CONNECT tüneli kurar ve bazı WAF'lar proxy başlıklarını denetleyebilir. SOCKS5 ise tamamen şeffaf bir tünel sunar — HTTP başlıklarında hiçbir proxy eseri kalmaz:

const browser = await puppeteer.launch({
  headless: 'new',
  args: [
    '--no-sandbox',
    `--proxy-server=socks5://gate.proxyhat.com:1080`
  ]
});

Özel Değerlendiriciler: Canvas ve WebGL Parmak İzi Rastgeleleştirme

Stealth plugin temel sızıntıları kapatır, ancak canvas fingerprint ve WebGL render parametreleri hala benzersiz tanımlayıcılar üretir. Her oturumda tutarlı ama oturumlar arasında farklı olan parmak izleri üretmek için özel evaluateOnNewDocument hook'ları yazmalısınız:

const crypto = require('crypto');

function generateSessionSeed() {
  return crypto.randomBytes(16).toString('hex');
}

async function applyFingerprintRandomization(page, seed) {
  await page.evaluateOnNewDocument((sessionSeed) => {
    // Canvas fingerprint rastgeleleştirme
    const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
    HTMLCanvasElement.prototype.toDataURL = function (...args) {
      const context = this.getContext('2d');
      if (context) {
        // Her oturumda benzersiz ama tutarlı gürültü ekle
        const noise = parseInt(sessionSeed.slice(0, 8), 16) % 5 - 2;
        const imageData = context.getImageData(0, 0, this.width, this.height);
        for (let i = 0; i < imageData.data.length; i += 4) {
          imageData.data[i] = Math.max(0, Math.min(255, imageData.data[i] + noise));
        }
        context.putImageData(imageData, 0, 0);
      }
      return originalToDataURL.apply(this, args);
    };

    // WebGL vendor/renderer rastgeleleştirme
    const getParameter = WebGLRenderingContext.prototype.getParameter;
    WebGLRenderingContext.prototype.getParameter = function (param) {
      if (param === 0x1F00) return 'Google Inc. (NVIDIA)'; // VENDOR
      if (param === 0x1F01) { // RENDERER
        const renderers = [
          'ANGLE (NVIDIA, NVIDIA GeForce GTX 1060)',
          'ANGLE (NVIDIA, NVIDIA GeForce RTX 3060)',
          'ANGLE (Intel, Intel(R) UHD Graphics 630)'
        ];
        const idx = parseInt(sessionSeed.slice(8, 12), 16) % renderers.length;
        return renderers[idx];
      }
      return getParameter.call(this, param);
    };
  }, seed);
}

// Kullanım
(async () => {
  const browser = await puppeteer.launch({ headless: 'new' });
  const page = await browser.newPage();
  const seed = generateSessionSeed();
  await applyFingerprintRandomization(page, seed);
  await page.goto('https://browserleaks.com/canvas');
  // ...
})();

Her yeni sayfa veya tarayıcı bağlamı için yeni bir seed üretin. Aynı seed, aynı oturum içinde tutarlı parmak izi verir — bu da parmak izi tutarlılık kontrollerini geçmenizi sağlar.

Tarayıcı Bağlamı Başına Proxy Rotasyonu

Tek bir tarayıcı örneğinde birden fazla BrowserContext açarak, her bağlama farklı bir proxy atayabilirsiniz. Bu, paralel kazıma senaryolarında IP rotasyonunu verimli hale getirir:

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

puppeteer.use(StealthPlugin());

const PROXY_CONFIGS = [
  { username: 'user-country-US', password: 'PASSWORD', country: 'US' },
  { username: 'user-country-DE', password: 'PASSWORD', country: 'DE' },
  { username: 'user-country-JP', password: 'PASSWORD', country: 'JP' }
];

async function createContextWithProxy(browser, config) {
  const context = await browser.createIncognitoBrowserContext();
  const page = await context.newPage();

  await page.authenticate({
    username: config.username,
    password: config.password
  });

  // Her bağlam için benzersiz parmak izi
  const seed = crypto.randomBytes(16).toString('hex');
  await applyFingerprintRandomization(page, seed);

  return { context, page, seed };
}

(async () => {
  const browser = await puppeteer.launch({
    headless: 'new',
    args: [
      '--no-sandbox',
      `--proxy-server=http://gate.proxyhat.com:8080`
    ]
  });

  const sessions = await Promise.all(
    PROXY_CONFIGS.map(cfg => createContextWithProxy(browser, cfg))
  );

  // Her bağlamı farklı ülke hedefiyle paralel kullan
  for (const session of sessions) {
    await session.page.goto('https://httpbin.org/ip');
    const ip = await session.page.evaluate(() =>
      document.querySelector('pre').innerText
    );
    console.log(`${session.seed.slice(0, 8)} IP:`, ip);
  }

  await browser.close();
})();
Önemli Not: --proxy-server bayrağı tarayıcı düzeyinde ayarlanır ve tüm bağlamları etkiler. page.authenticate() ile her bağlama farklı kimlik bilgisi vererek, ProxyHat'ın ülke hedefleme mekanizması üzerinden bağlam bazlı rotasyon sağlayabilirsiniz. Her bağlamın farklı bir ülke IP'si almasını sağlamak için kullanıcı adı içindeki country parametresini değiştirin.

Sticky Oturumlar ile Tutarlı IP

Bazı senaryolarda (oturum açma, sepet işlemleri) aynı IP'de kalmanız gerekir. ProxyHat'ın sticky session özelliğini kullanmak için kullanıcı adında bir session parametresi ekleyin:

await page.authenticate({
  username: 'user-country-US-session-abc123',
  password: 'PASSWORD'
});

Aynı session tanımlayıcısını kullanan tüm istekler aynı yerel IP'ye yönlendirilir — oturum süresi boyunca tutarlı kalır.

Ölçeklendirme: Konteynerleştirilmiş Filolar ve Tarayıcı Havuzları

Tek bir makinede yüzlerce paralel tarayıcı çalıştırmak kaynak yönetimi kabusudur. Doğru yaklaşım, konteynerleştirilmiş tarayıcı filoları oluşturmaktır.

Docker ile İzole Tarayıcı Düğümleri

Her Docker konteyneri bir tarayıcı örneği çalıştırır. Bu, bellek izolasyonu, bağımsız ölçeklendirme ve temiz başlangıç garantisi sağlar:

FROM node:20-slim

RUN apt-get update && apt-get install -y \
    chromium \
    fonts-ipafont-gothic \
    --no-install-recommends && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .

ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
ENV MAX_CONCURRENT_PAGES=5
ENV PROXY_GATEWAY=http://gate.proxyhat.com:8080

CMD ["node", "worker.js"]

Tarayıcı Havuzu Yönetimi

Ölçeklendirme sırasında tarayıcı yaşam döngüsünü yönetmek için bir havuz soyutlaması kullanın. Her worker şöyle çalışır:

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
const crypto = require('crypto');

puppeteer.use(StealthPlugin());

class BrowserPool {
  constructor({ maxBrowsers = 4, maxPagesPerBrowser = 5 } = {}) {
    this.maxBrowsers = maxBrowsers;
    this.maxPagesPerBrowser = maxPagesPerBrowser;
    this.browsers = [];
  }

  async acquirePage(proxyConfig) {
    // Mevcut tarayıcılarda boş yuva ara
    for (const entry of this.browsers) {
      if (entry.pageCount < this.maxPagesPerBrowser) {
        const context = await entry.browser.createIncognitoBrowserContext();
        const page = await context.newPage();
        await page.authenticate({
          username: proxyConfig.username,
          password: proxyConfig.password
        });
        const seed = crypto.randomBytes(16).toString('hex');
        await applyFingerprintRandomization(page, seed);
        entry.pageCount++;

        const originalClose = page.close.bind(page);
        page.close = async () => {
          await originalClose();
          await context.close();
          entry.pageCount--;
        };

        return page;
      }
    }

    // Yeni tarayıcı başlat
    if (this.browsers.length < this.maxBrowsers) {
      const browser = await puppeteer.launch({
        headless: 'new',
        executablePath: process.env.PUPPETEER_EXECUTABLE_PATH,
        args: [
          '--no-sandbox',
          '--disable-setuid-sandbox',
          '--disable-dev-shm-usage',
          `--proxy-server=${process.env.PROXY_GATEWAY}`
        ]
      });

      const entry = { browser, pageCount: 0 };
      this.browsers.push(entry);
      return this.acquirePage(proxyConfig);
    }

    throw new Error('Tarayıcı havuzu dolu — daha sonra tekrar deneyin');
  }

  async drain() {
    await Promise.all(this.browsers.map(e => e.browser.close()));
    this.browsers = [];
  }
}

module.exports = { BrowserPool };

Kaynak Yönetimi En İyi Uygulamaları

  • Bellek sınırı: Her Chromium örneği ~150-300 MB bellek tüketir. Konteyner başına en az 512 MB ayırın ve --disable-dev-shm-usage bayrağını kullanın.
  • Sayfa yaşam süresi: Her sayfayı 30 saniyeden uzun açık tutmayın. Bellek sızıntıları birikir ve tarayıcıyı çökertir.
  • Otomatik yeniden başlatma: Tarayıcıları her 50-100 sayfadan sonra yeniden başlatın. Chromium'un bellek parçalanması kaçınılmazdır.
  • İstek zaman aşımı: Proxy üzerinden yapılan isteklerde 30 saniye zaman aşımı ayarlayın. Yerel proxy'ler veri merkezi proxy'lere göre biraz daha yüksek gecikmeye sahip olabilir.
  • Hata oranı izleme: Başarı oranını dakika bazında izleyin. %90'ın altına düşerse, proxy sağlayıcınızın durum sayfasını kontrol edin.

Kubernetes ile Yatay Ölçeklendirme

Üretim ortamında Kubernetes Deployment + HPA (Horizontal Pod Autoscaler) kullanarak CPU/bellek eşiklerine göre otomatik ölçeklendirme yapın. Her Pod bir worker çalıştırır ve ProxyHat'ın oturum bazlı rotasyonu ile çakışma riski olmadan binlerce eşzamanlı oturum yönetebilirsiniz.

Etik Not: Stealth Meşru Kazıma İçindir

Anti-tespit teknikleri güçlü araçlardır ve güçlü araçlar sorumlu kullanım gerektirir. Stealth plugin ve yerel proxy'ler şu amaçlarla kullanılmalıdır:

  • SERP izleme ve arama motoru verisi toplama
  • E-ticaret fiyat karşılaştırma ve pazar analizi
  • Genel erişimli verilerin toplanması
  • QA ve erişilebilirlik testleri
  • Güvenlik araştırmaları

Bu teknikler asla dolandırıcılık, kimlik sahteciliği, kredi kartı testi veya hizmet koşullarını açıkça ihlal eden faaliyetler için kullanılmamalıdır. Her zaman robots.txt'e saygı gösterin, rate limiting uygulayın ve hedef sitenin altyapısını aşırı yüklemeyin. GDPR ve CCPA kapsamındaki kişisel veri toplama kurallarına uyun. ProxyHat'ın kullanım koşulları da bu etik çerçeveyi gerektirir.

Temel Çıkarımlar

  • Raw Puppeteer en az üç bariz sinyal sızdırır: navigator.webdriver, tutarsız plugins dizisi ve ChromeDriver iframe eserleri.
  • puppeteer-extra-plugin-stealth dokuz alt modülle bu sızıntıları sistematik olarak kapatır.
  • Stealth tek başına yeterli değildir — yerel proxy'lerle birleştirilmeden IP bazlı engellemeler kaçınılmazdır.
  • Canvas ve WebGL parmak izlerini her oturumda rastgeleleştirmek için evaluateOnNewDocument hook'ları yazın.
  • BrowserContext başına proxy rotasyonu, paralel kazımada IP çeşitliliği sağlar.
  • Ölçeklendirme için konteynerleştirilmiş filolar, tarayıcı havuzları ve düzenli yeniden başlatma stratejileri kullanın.
  • Etik kurallara uyun — stealth meşru kazıma içindir, dolandırıcılık değil.

ProxyHat'ın yerel proxy ağı, 190+ ülkede IP rotasyonu ve şehir düzeyinde hedefleme sunar. Ücretsiz deneme ile fiyatlandırma sayfamızı inceleyin veya doğrudan bu rehberdeki kod örneklerini projenize entegre edin. Daha fazla kazıma deseni için web kazıma kullanım senaryomuzu ve SERP izleme sayfamızı ziyaret edin.

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