Kembali ke blog

Cara Menyembunyikan Penggunaan Selenium dan Puppeteer

Pelajari cara efektif menyembunyikan penggunaan Selenium dan Puppeteer dari sistem perlindungan anti-bot. Metode praktis, contoh kode, dan teknik penyamaran otomatisasi yang terbukti.

📅26 Desember 2025
```html

Panduan Lengkap untuk Menyamarkan Selenium dan Puppeteer dari Deteksi

Sistem perlindungan anti-bot modern dengan mudah mengenali browser otomatisasi berdasarkan puluhan tanda: dari variabel JavaScript hingga karakteristik perilaku WebDriver. Situs web menggunakan Cloudflare, DataDome, PerimeterX, dan solusi mereka sendiri yang memblokir hingga 90% permintaan dari Selenium dan Puppeteer dalam konfigurasi standar.

Dalam panduan ini, kita akan membahas semua metode penyamaran otomatisasi: dari pengaturan dasar hingga teknik lanjutan untuk menghindari deteksi. Anda akan mendapatkan solusi siap pakai dengan contoh kode untuk Python dan Node.js yang bekerja melawan sebagian besar sistem perlindungan.

Bagaimana situs mendeteksi otomatisasi

Sistem perlindungan anti-bot menganalisis browser berdasarkan banyak parameter secara bersamaan. Bahkan jika Anda menyembunyikan satu tanda, yang lainnya akan mengungkapkan otomatisasi. Memahami semua metode deteksi adalah kunci untuk penyamaran yang efektif.

Indikator WebDriver

Metode paling sederhana untuk mendeteksi adalah dengan memeriksa variabel JavaScript yang hanya ada di browser otomatisasi:

// Variabel ini mengungkapkan Selenium/Puppeteer
navigator.webdriver === true
window.navigator.webdriver === true
document.$cdc_ // Variabel spesifik ChromeDriver
window.document.documentElement.getAttribute("webdriver")
navigator.plugins.length === 0 // Browser otomatisasi tidak memiliki plugin
navigator.languages === "" // Daftar bahasa kosong

Cloudflare dan sistem serupa memeriksa properti ini terlebih dahulu. Jika salah satu dari mereka mengembalikan hasil positif — permintaan akan diblokir.

Fingerprinting Browser

Sistem canggih membuat sidik jari unik browser berdasarkan puluhan parameter:

  • Canvas Fingerprinting — merender gambar tersembunyi dan menganalisis data piksel
  • WebGL Fingerprinting — parameter renderer grafis dan kartu grafis
  • Audio Context — karakteristik unik pemrosesan audio
  • Fonts Fingerprinting — daftar font yang terpasang di sistem
  • Screen Resolution — resolusi layar, kedalaman warna, area yang tersedia
  • Timezone & Language — zona waktu, bahasa browser, lokal sistem

Browser otomatisasi sering memiliki kombinasi parameter yang tidak biasa. Misalnya, Headless Chrome tidak memiliki plugin, tetapi mendukung WebGL — kombinasi seperti itu sangat jarang ditemukan pada pengguna nyata.

Analisis Perilaku

Sistem modern melacak pola perilaku:

  • Gerakan mouse — bot menggerakkan kursor dalam garis lurus atau tidak bergerak sama sekali
  • Kecepatan tindakan — pengisian formulir instan, kecepatan klik yang tidak manusiawi
  • Pola scrolling — lompatan tajam alih-alih scrolling yang halus
  • Peristiwa keyboard — tidak ada jeda alami antara penekanan
  • Frekuensi permintaan — interval yang terlalu teratur antara tindakan

Penting: DataDome dan PerimeterX menggunakan pembelajaran mesin untuk menganalisis perilaku. Mereka dilatih pada jutaan sesi dan dapat mengenali bot bahkan dengan penyamaran parameter teknis yang benar, jika perilakunya terlihat tidak alami.

Penyamaran Dasar Selenium

Selenium WebDriver dalam konfigurasi standar meninggalkan banyak jejak. Mari kita lihat pengaturan langkah demi langkah untuk meminimalkan deteksi dengan contoh Python dan ChromeDriver.

Menonaktifkan Flag WebDriver

Langkah pertama adalah menyembunyikan variabel navigator.webdriver. Ini dilakukan melalui Chrome DevTools Protocol:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

# Mengatur opsi Chrome
chrome_options = Options()

# Menonaktifkan flag otomatisasi
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)

# Membuat driver
driver = webdriver.Chrome(options=chrome_options)

# Menghapus webdriver melalui CDP
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        })
    '''
})

driver.get('https://example.com')

Mengatur User-Agent dan Header Lainnya

Browser headless sering menggunakan string User-Agent yang usang atau spesifik. Anda perlu mengatur User-Agent yang relevan dari browser nyata:

# User-Agent Chrome yang relevan di Windows
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
chrome_options.add_argument(f'user-agent={user_agent}')

# Argumen tambahan untuk penyamaran
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-gpu')

# Ukuran jendela seperti pengguna nyata
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--start-maximized')

Menambahkan Plugin dan Bahasa

Browser otomatisasi tidak memiliki plugin dan sering menunjukkan daftar bahasa yang kosong. Kita bisa memperbaikinya melalui CDP:

driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'languages', {
            get: () => ['en-US', 'en', 'ru']
        });
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [
                {
                    0: {type: "application/x-google-chrome-pdf", suffixes: "pdf", description: "Portable Document Format"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Plugin"
                },
                {
                    0: {type: "application/pdf", suffixes: "pdf", description: ""},
                    description: "",
                    filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai",
                    length: 1,
                    name: "Chrome PDF Viewer"
                }
            ]
        });
        
        Object.defineProperty(navigator, 'platform', {
            get: () => 'Win32'
        });
    '''
})

Contoh Lengkap Pengaturan Selenium

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import random

def create_stealth_driver():
    chrome_options = Options()
    
    # Pengaturan dasar penyamaran
    chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
    chrome_options.add_experimental_option('useAutomationExtension', False)
    chrome_options.add_argument('--disable-blink-features=AutomationControlled')
    
    # User-Agent
    user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
    chrome_options.add_argument(f'user-agent={user_agent}')
    
    # Ukuran jendela
    chrome_options.add_argument('--window-size=1920,1080')
    chrome_options.add_argument('--start-maximized')
    
    driver = webdriver.Chrome(options=chrome_options)
    
    # Skrip penyamaran melalui CDP
    stealth_script = '''
        Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
        Object.defineProperty(navigator, 'languages', {get: () => ['en-US', 'en']});
        Object.defineProperty(navigator, 'platform', {get: () => 'Win32'});
        
        window.chrome = {
            runtime: {}
        };
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [1, 2, 3, 4, 5]
        });
    '''
    
    driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
        'source': stealth_script
    })
    
    return driver

# Penggunaan
driver = create_stealth_driver()
driver.get('https://bot.sannysoft.com/')  # Situs untuk memeriksa deteksi

Pengaturan Puppeteer untuk menghindari deteksi

Puppeteer memiliki masalah deteksi yang sama dengan Selenium. Namun, untuk Node.js ada perpustakaan siap pakai puppeteer-extra-plugin-stealth yang mengotomatiskan sebagian besar pengaturan penyamaran.

Instalasi puppeteer-extra

npm install puppeteer puppeteer-extra puppeteer-extra-plugin-stealth

Konfigurasi Dasar dengan Plugin Stealth

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

// Menggunakan plugin penyamaran
puppeteer.use(StealthPlugin());

(async () => {
    const browser = await puppeteer.launch({
        headless: 'new', // Mode headless baru Chrome
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-dev-shm-usage',
            '--disable-accelerated-2d-canvas',
            '--disable-gpu',
            '--window-size=1920,1080',
            '--disable-web-security',
            '--disable-features=IsolateOrigins,site-per-process'
        ]
    });
    
    const page = await browser.newPage();
    
    // Mengatur viewport
    await page.setViewport({
        width: 1920,
        height: 1080,
        deviceScaleFactor: 1
    });
    
    // Mengatur User-Agent
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
    
    // Header tambahan
    await page.setExtraHTTPHeaders({
        'Accept-Language': 'en-US,en;q=0.9',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
    });
    
    await page.goto('https://bot.sannysoft.com/');
    
    // Screenshot untuk pemeriksaan
    await page.screenshot({ path: 'test.png' });
    
    await browser.close();
})();

Pengaturan Manual Tanpa Plugin

Jika Anda ingin kontrol penuh atau tidak dapat menggunakan perpustakaan pihak ketiga, atur penyamaran secara manual:

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: ['--no-sandbox', '--disable-setuid-sandbox']
    });
    
    const page = await browser.newPage();
    
    // Mengoverride webdriver dan properti lainnya
    await page.evaluateOnNewDocument(() => {
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        });
        
        Object.defineProperty(navigator, 'languages', {
            get: () => ['en-US', 'en']
        });
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [1, 2, 3, 4, 5]
        });
        
        // Menyamarkan Chrome headless
        Object.defineProperty(navigator, 'platform', {
            get: () => 'Win32'
        });
        
        window.chrome = {
            runtime: {}
        };
        
        // Mengoverride permissions
        const originalQuery = window.navigator.permissions.query;
        window.navigator.permissions.query = (parameters) => (
            parameters.name === 'notifications' ?
                Promise.resolve({ state: Notification.permission }) :
                originalQuery(parameters)
        );
    });
    
    await page.goto('https://example.com');
    await browser.close();
})();

Pengaturan untuk Menghindari Cloudflare

Cloudflare menggunakan metode deteksi canggih. Untuk menghindarinya, perlu menambahkan jeda acak dan emulasi tindakan:

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

puppeteer.use(StealthPlugin());

async function bypassCloudflare(url) {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-web-security'
        ]
    });
    
    const page = await browser.newPage();
    
    // User-Agent acak
    const userAgents = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
    ];
    await page.setUserAgent(userAgents[Math.floor(Math.random() * userAgents.length)]);
    
    // Mengunjungi halaman
    await page.goto(url, { waitUntil: 'networkidle2' });
    
    // Menunggu pemeriksaan Cloudflare (biasanya 5-10 detik)
    await page.waitForTimeout(8000);
    
    // Gerakan mouse acak
    await page.mouse.move(100, 100);
    await page.mouse.move(200, 200);
    
    const content = await page.content();
    await browser.close();
    
    return content;
}

Melawan JavaScript Fingerprinting

JavaScript fingerprinting adalah pembuatan sidik jari unik browser berdasarkan banyak parameter. Bahkan jika Anda menyembunyikan webdriver, sistem menganalisis ratusan properti lain untuk mengidentifikasi otomatisasi.

Vektor Utama Fingerprinting

Sistem perlindungan anti-bot memeriksa parameter berikut:

Parameter Apa yang Diperiksa Risiko Deteksi
navigator.webdriver Keberadaan flag otomatisasi Kritis
navigator.plugins Jumlah dan jenis plugin Tinggi
window.chrome Keberadaan API Chrome Sedang
navigator.permissions API izin browser Sedang
screen.colorDepth Kedalaman warna layar Rendah
navigator.hardwareConcurrency Jumlah inti prosesor Rendah

Skrip Penyamar Kompleks

Skrip di bawah ini mengoverride sebagian besar properti bermasalah. Terapkan melalui CDP (Selenium) atau evaluateOnNewDocument (Puppeteer):

const stealthScript = `
    // Menghapus webdriver
    Object.defineProperty(navigator, 'webdriver', {
        get: () => undefined
    });
    
    // Menambahkan objek chrome
    window.chrome = {
        runtime: {},
        loadTimes: function() {},
        csi: function() {},
        app: {}
    };
    
    // Mengoverride permissions
    const originalQuery = window.navigator.permissions.query;
    window.navigator.permissions.query = (parameters) => (
        parameters.name === 'notifications' ?
            Promise.resolve({ state: Notification.permission }) :
            originalQuery(parameters)
    );
    
    // Menyamarkan plugin
    Object.defineProperty(navigator, 'plugins', {
        get: () => {
            return [
                {
                    0: {type: "application/x-google-chrome-pdf", suffixes: "pdf"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Plugin"
                },
                {
                    0: {type: "application/pdf", suffixes: "pdf"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Viewer"
                },
                {
                    0: {type: "application/x-nacl"},
                    description: "Native Client Executable",
                    filename: "internal-nacl-plugin",
                    length: 2,
                    name: "Native Client"
                }
            ];
        }
    });
    
    // Bahasa
    Object.defineProperty(navigator, 'languages', {
        get: () => ['en-US', 'en']
    });
    
    // Platform
    Object.defineProperty(navigator, 'platform', {
        get: () => 'Win32'
    });
    
    // Vendor
    Object.defineProperty(navigator, 'vendor', {
        get: () => 'Google Inc.'
    });
    
    // Menghapus jejak Selenium
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;
    
    // Battery API (tidak ada di headless)
    if (!navigator.getBattery) {
        navigator.getBattery = () => Promise.resolve({
            charging: true,
            chargingTime: 0,
            dischargingTime: Infinity,
            level: 1
        });
    }
`;

Menghapus Properti WebDriver

ChromeDriver dan implementasi WebDriver lainnya menambahkan variabel spesifik ke ruang lingkup global. Variabel ini dimulai dengan awalan cdc_ dan mudah dideteksi oleh sistem perlindungan.

Deteksi Variabel cdc

Memeriksa keberadaan variabel ini dapat dilakukan dengan skrip sederhana:

// Mencari semua variabel cdc
for (let key in window) {
    if (key.includes('cdc_')) {
        console.log('Variabel WebDriver terdeteksi:', key);
    }
}

// Variabel tipikal ChromeDriver:
// cdc_adoQpoasnfa76pfcZLmcfl_Array
// cdc_adoQpoasnfa76pfcZLmcfl_Promise
// cdc_adoQpoasnfa76pfcZLmcfl_Symbol
// $cdc_asdjflasutopfhvcZLmcfl_

Metode 1: Menghapus melalui CDP

Cara paling andal adalah menghapus variabel sebelum memuat halaman melalui Chrome DevTools Protocol:

from selenium import webdriver

driver = webdriver.Chrome()

# Menghapus semua variabel cdc
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        // Menghapus variabel cdc yang diketahui
        const cdcProps = [
            'cdc_adoQpoasnfa76pfcZLmcfl_Array',
            'cdc_adoQpoasnfa76pfcZLmcfl_Promise',
            'cdc_adoQpoasnfa76pfcZLmcfl_Symbol',
            '$cdc_asdjflasutopfhvcZLmcfl_'
        ];
        
        cdcProps.forEach(prop => {
            delete window[prop];
        });
        
        // Menghapus semua variabel yang mengandung 'cdc_'
        Object.keys(window).forEach(key => {
            if (key.includes('cdc_') || key.includes('$cdc_')) {
                delete window[key];
            }
        });
    '''
})

Metode 2: Modifikasi ChromeDriver

Pendekatan yang lebih radikal adalah mengubah file biner ChromeDriver, mengganti string cdc_ dengan urutan karakter lain. Ini mencegah pembuatan variabel tersebut:

import re

def patch_chromedriver(driver_path):
    """
    Memperbaiki ChromeDriver, mengganti 'cdc_' dengan string acak
    """
    with open(driver_path, 'rb') as f:
        content = f.read()
    
    # Mengganti semua kemunculan 'cdc_' dengan 'dog_' (atau string lain dengan panjang yang sama)
    patched = content.replace(b'cdc_', b'dog_')
    
    with open(driver_path, 'wb') as f:
        f.write(patched)
    
    print(f'ChromeDriver telah dipatch: {driver_path}')

# Penggunaan
patch_chromedriver('/path/to/chromedriver')

Perhatian: Modifikasi file biner ChromeDriver dapat merusak fungsinya. Selalu buat cadangan sebelum melakukan patch. Metode ini tidak berfungsi dengan semua versi ChromeDriver.

Metode 3: Menggunakan undetected-chromedriver

Perpustakaan undetected-chromedriver secara otomatis mempatch ChromeDriver saat dijalankan:

pip install undetected-chromedriver
import undetected_chromedriver as uc

# Membuat driver dengan pemrograman otomatis
driver = uc.Chrome()

driver.get('https://nowsecure.nl/')  # Situs untuk memeriksa deteksi
input('Tekan Enter untuk menutup...')
driver.quit()

Menyamarkan Canvas, WebGL, dan Audio API

Canvas, WebGL, dan Audio Fingerprinting adalah metode untuk membuat sidik jari unik berdasarkan karakteristik rendering grafis dan pemrosesan suara. Setiap kombinasi browser, OS, dan perangkat keras memberikan hasil yang unik.

Canvas Fingerprinting

Sistem menggambar gambar tersembunyi pada Canvas dan menganalisis piksel yang dihasilkan. Browser headless sering memberikan hasil yang tidak biasa karena tidak adanya akselerasi GPU.

// Kode tipikal Canvas Fingerprinting
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillText('Browser fingerprint', 2, 2);
const fingerprint = canvas.toDataURL();

Untuk perlindungan, Anda dapat menambahkan kebisingan acak ke API Canvas:

const canvasNoiseScript = `
    // Menambahkan kebisingan acak ke Canvas
    const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
    const originalToBlob = HTMLCanvasElement.prototype.toBlob;
    const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
    
    // Fungsi untuk menambahkan kebisingan
    const addNoise = (canvas, context) => {
        const imageData = originalGetImageData.call(context, 0, 0, canvas.width, canvas.height);
        for (let i = 0; i < imageData.data.length; i += 4) {
            // Menambahkan kebisingan minimal ke RGB (tidak terlihat oleh mata)
            imageData.data[i] += Math.floor(Math.random() * 3) - 1;
            imageData.data[i + 1] += Math.floor(Math.random() * 3) - 1;
            imageData.data[i + 2] += Math.floor(Math.random() * 3) - 1;
        }
        context.putImageData(imageData, 0, 0);
    };
    
    // Mengoverride toDataURL
    HTMLCanvasElement.prototype.toDataURL = function() {
        if (this.width > 0 && this.height > 0) {
            const context = this.getContext('2d');
            addNoise(this, context);
        }
        return originalToDataURL.apply(this, arguments);
    };
`;

WebGL Fingerprinting

WebGL memberikan informasi tentang kartu grafis dan driver. Browser headless sering menunjukkan SwiftShader (renderer perangkat lunak) alih-alih GPU nyata:

const webglMaskScript = `
    // Menyamarkan parameter WebGL
    const getParameter = WebGLRenderingContext.prototype.getParameter;
    WebGLRenderingContext.prototype.getParameter = function(parameter) {
        // UNMASKED_VENDOR_WEBGL
        if (parameter === 37445) {
            return 'Intel Inc.';
        }
        // UNMASKED_RENDERER_WEBGL
        if (parameter === 37446) {
            return 'Intel Iris OpenGL Engine';
        }
        return getParameter.call(this, parameter);
    };
    
    // Juga untuk WebGL2
    if (typeof WebGL2RenderingContext !== 'undefined') {
        const getParameter2 = WebGL2RenderingContext.prototype.getParameter;
        WebGL2RenderingContext.prototype.getParameter = function(parameter) {
            if (parameter === 37445) {
                return 'Intel Inc.';
            }
            if (parameter === 37446) {
                return 'Intel Iris OpenGL Engine';
            }
            return getParameter2.call(this, parameter);
        };
    }
`;

Audio Context Fingerprinting

Audio API juga memberikan sidik jari unik. Tambahkan kebisingan ke pemrosesan audio:

const audioMaskScript = `
    // Menambahkan kebisingan ke Audio Context
    const AudioContext = window.AudioContext || window.webkitAudioContext;
    if (AudioContext) {
        const originalCreateAnalyser = AudioContext.prototype.createAnalyser;
        AudioContext.prototype.createAnalyser = function() {
            const analyser = originalCreateAnalyser.call(this);
            const originalGetFloatFrequencyData = analyser.getFloatFrequencyData;
            analyser.getFloatFrequencyData = function(array) {
                originalGetFloatFrequencyData.call(this, array);
                // Menambahkan kebisingan minimal
                for (let i = 0; i < array.length; i++) {
                    array[i] += Math.random() * 0.0001;
                }
            };
            return analyser;
        };
    }
`;

Meniru Perilaku Manusia

Bahkan dengan penyamaran teknis yang sempurna, bot mengungkapkan diri mereka melalui perilaku. Sistem pembelajaran mesin menganalisis pola gerakan mouse, kecepatan tindakan, dan urutan peristiwa.

Jeda Acak Antara Tindakan

Jangan pernah menggunakan jeda tetap. Pengguna nyata membuat jeda dengan durasi yang bervariasi:

import random
import time

def human_delay(min_seconds=1, max_seconds=3):
    """Jeda acak yang meniru manusia"""
    delay = random.uniform(min_seconds, max_seconds)
    time.sleep(delay)

# Penggunaan
driver.get('https://example.com')
human_delay(2, 4)  # Jeda 2-4 detik

element = driver.find_element(By.ID, 'search')
human_delay(0.5, 1.5)  # Jeda singkat sebelum memasukkan

element.send_keys('search query')
human_delay(1, 2)

Gerakan Mouse yang Halus

Bot menggerakkan mouse dalam garis lurus atau teleport kursor. Pengguna nyata menciptakan jalur melengkung dengan percepatan dan perlambatan:

// Puppeteer: gerakan mouse yang halus
async function humanMouseMove(page, targetX, targetY) {
    const steps = 25; // Jumlah titik perantara
    const currentPos = await page.evaluate(() => ({
        x: window.mouseX || 0,
        y: window.mouseY || 0
    }));
    
    for (let i = 0; i <= steps; i++) {
        const t = i / steps;
        // Menggunakan easing untuk kelancaran
        const ease = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
        
        const x = currentPos.x + (targetX - currentPos.x) * ease;
        const y = currentPos.y + (targetY - currentPos.y) * ease;
        
        await page.mouse.move(x, y);
        await page.waitForTimeout(Math.random() * 10 + 5);
    }
    
    // Menyimpan posisi
    await page.evaluate((x, y) => {
        window.mouseX = x;
        window.mouseY = y;
    }, targetX, targetY);
}

// Penggunaan
await humanMouseMove(page, 500, 300);
await page.mouse.click(500, 300);

Scrolling yang Alami

Pengguna nyata menggulir dengan halus, dengan jeda untuk membaca konten:

async function humanScroll(page) {
    const scrollHeight = await page.evaluate(() => document.body.scrollHeight);
    const viewportHeight = await page.evaluate(() => window.innerHeight);
    
    let currentPosition = 0;
    
    while (currentPosition < scrollHeight - viewportHeight) {
        // Langkah gulir acak (200-500px)
        const scrollStep = Math.floor(Math.random() * 300) + 200;
        currentPosition += scrollStep;
        
        // Gulir halus
        await page.evaluate((pos) => {
            window.scrollTo({
                top: pos,
                behavior: 'smooth'
            });
        }, currentPosition);
        
        // Jeda untuk "membaca" konten (1-3 detik)
        await page.waitForTimeout(Math.random() * 2000 + 1000);
    }
}

// Penggunaan
await page.goto('https://example.com');
await humanScroll(page);

Memasukkan Teks yang Alami

Orang mengetik dengan kecepatan yang bervariasi, membuat kesalahan ketik, dan memperbaikinya:

async function humanTypeText(page, selector, text) {
    await page.click(selector);
    
    for (let char of text) {
        // Jeda acak antara penekanan (50-200ms)
        const delay = Math.random() * 150 + 50;
        await page.waitForTimeout(delay);
        
        // 5% kemungkinan kesalahan ketik
        if (Math.random() < 0.05) {
            // Mengetik karakter acak
            const wrongChar = String.fromCharCode(97 + Math.floor(Math.random() * 26));
            await page.keyboard.type(wrongChar);
            await page.waitForTimeout(100 + Math.random() * 100);
            // Menghapus (Backspace)
            await page.keyboard.press('Backspace');
            await page.waitForTimeout(50 + Math.random() * 50);
        }
        
        await page.keyboard.type(char);
    }
}

// Penggunaan
await humanTypeText(page, '#search-input', 'example search query');

Integrasi Proxy untuk Anonimitas Penuh

Menyamarkan browser tidak ada gunanya jika semua permintaan berasal dari satu alamat IP. Sistem perlindungan anti-bot melacak jumlah permintaan dari setiap IP dan memblokir aktivitas yang mencurigakan. Proxy adalah komponen wajib dari setiap otomatisasi serius.

Memilih Jenis Proxy

Tugas yang berbeda memerlukan jenis proxy yang berbeda:

Jenis Proxy Keuntungan Penerapan
Proxy Residental Tampak seperti pengguna nyata Scraping, otomatisasi
Proxy Data Center Cepat dan murah Pengujian, scraping
Proxy Terbalik Menyembunyikan alamat IP asli Akses data, scraping
```