Quay lại blog

Cài đặt proxy trong Playwright cho kiểm thử headless và parsing: hướng dẫn đầy đủ

Phân tích cách kết nối proxy đúng cách trong Playwright cho kiểm thử headless và parsing - với ví dụ mã, xoay vòng IP và vượt qua bảo vệ chống bot.

📅8 tháng 5, 2026
```html

Playwright là một trong những công cụ mạnh mẽ nhất để tự động hóa trình duyệt, kiểm thử headless và thu thập dữ liệu. Nhưng nếu không có proxy được cấu hình đúng cách, kịch bản của bạn sẽ nhanh chóng bị chặn theo IP: các trang web đã học cách nhận diện các yêu cầu tự động và chặn chúng. Trong hướng dẫn này, chúng ta sẽ phân tích tất cả các cách kết nối proxy trong Playwright - từ cấu hình cơ bản đến xoay vòng IP và vượt qua Cloudflare.

Tại sao cần proxy trong Playwright và khi nào không thể thiếu nó

Playwright khởi động trình duyệt thực (Chromium, Firefox hoặc WebKit) ở chế độ nền - đó là headless. Từ quan điểm của trang web, bạn trông giống như một người dùng bình thường, nhưng chỉ đến một thời điểm nhất định. Ngay khi từ một IP bắt đầu có hàng trăm yêu cầu mỗi giờ, các thuật toán bảo vệ phản ứng ngay lập tức: CAPTCHA, chặn tạm thời, chặn hoàn toàn.

Dưới đây là những kịch bản cụ thể mà proxy là bắt buộc:

  • Thu thập dữ liệu từ các chợ trực tuyến - Wildberries, Ozon, Avito, Yandex.Market chặn các kịch bản sau 50–100 yêu cầu từ một IP.
  • Theo dõi giá của đối thủ - nếu kiểm tra mỗi 15 phút, mà không thay đổi IP, bạn sẽ bị chặn trong vài giờ.
  • Kiểm thử định vị địa lý - cần kiểm tra trang web hiển thị như thế nào cho người dùng từ Đức, Mỹ hoặc Kazakhstan.
  • Điền biểu mẫu và đăng ký tài khoản - các nền tảng liên kết tài khoản với IP và chặn đăng ký hàng loạt.
  • Theo dõi SEO - thu thập vị trí từ Google và Yandex yêu cầu thay đổi IP liên tục, nếu không công cụ tìm kiếm sẽ hiển thị CAPTCHA.
  • Kiểm thử các chức năng A/B - một số tính năng chỉ có sẵn cho người dùng từ các quốc gia hoặc khu vực nhất định.

Quan trọng là hiểu rằng: Playwright tự nó không làm bạn ẩn danh. Nếu không có proxy, tất cả các yêu cầu đều đến từ địa chỉ IP thực của bạn. Thêm proxy là bước đầu tiên và quan trọng nhất để có được sự ổn định cho bất kỳ kịch bản tự động hóa nào.

💡 Điều quan trọng cần biết

Playwright hỗ trợ proxy ở cấp độ toàn bộ trình duyệt, ngữ cảnh riêng (BrowserContext) và thậm chí là trang riêng. Điều này mang lại sự linh hoạt: các trang khác nhau có thể hoạt động qua các IP khác nhau cùng một lúc.

Loại proxy nào nên chọn cho tự động hóa headless

Không phải tất cả các proxy đều phù hợp như nhau cho Playwright. Lựa chọn phụ thuộc vào nhiệm vụ: bạn đang thu thập dữ liệu gì, mức độ bảo vệ của trang web ra sao và khối lượng yêu cầu bạn dự định thực hiện.

Loại proxy Mức độ tin cậy Tốc độ Phù hợp cho
Data-center Thấp Rất cao Thu thập dữ liệu không có bảo vệ nghiêm ngặt, kiểm thử
Residential Cao Trung bình Các trang web với Cloudflare, chợ trực tuyến, mạng xã hội
Mobile Tối đa Trung bình Facebook, TikTok, Instagram, bảo vệ chống bot nghiêm ngặt
SOCKS5 Phụ thuộc vào nguồn Cao Giao thức đa năng, được Playwright hỗ trợ

Đối với hầu hết các nhiệm vụ thu thập dữ liệu, lựa chọn tối ưu là proxy residential với xoay vòng. Chúng có IP thực của người dùng tại nhà, vì vậy các trang web không xác định chúng là data-center và không chặn tự động. Đối với các trang web có bảo vệ nghiêm ngặt (Cloudflare Bot Management, Akamai), tốt hơn là sử dụng proxy mobile - IP của chúng thuộc về các nhà mạng di động, điều này tạo ra sự tin cậy tối đa.

Playwright hỗ trợ các giao thức http, httpssocks5. Quan trọng: SOCKS5 không hỗ trợ xác thực qua username:password trực tiếp trong một số phiên bản - điều này sẽ được giải thích chi tiết trong phần lỗi.

Cấu hình cơ bản proxy trong Playwright (JavaScript và Python)

Playwright cho phép bạn chỉ định proxy khi khởi động trình duyệt thông qua tham số proxy. Đây là cách đơn giản nhất - tất cả các yêu cầu của trình duyệt sẽ đi qua máy chủ proxy đã chỉ định.

JavaScript / Node.js

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

(async () => {
  const browser = await chromium.launch({
    proxy: {
      server: 'http://proxy.example.com:8080'
    }
  });

  const page = await browser.newPage();
  await page.goto('https://httpbin.org/ip');
  
  const content = await page.textContent('body');
  console.log(content); // sẽ hiển thị IP của máy chủ proxy

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

Python

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server": "http://proxy.example.com:8080"
        }
    )
    
    page = browser.new_page()
    page.goto("https://httpbin.org/ip")
    
    print(page.text_content("body"))  # sẽ hiển thị IP của proxy
    
    browser.close()

Đối với SOCKS5, chỉ cần thay đổi giao thức trong địa chỉ máy chủ:

# Python - proxy SOCKS5
browser = p.chromium.launch(
    proxy={
        "server": "socks5://proxy.example.com:1080"
    }
)

Để nhanh chóng kiểm tra xem proxy có hoạt động hay không, hãy mở https://httpbin.org/ip hoặc https://api.ipify.org - trong phản hồi phải là IP của máy chủ proxy, không phải IP thực của bạn.

Proxy với xác thực bằng tên đăng nhập và mật khẩu

Hầu hết các nhà cung cấp proxy thương mại sử dụng xác thực bằng tên đăng nhập và mật khẩu - đây là thực hành tiêu chuẩn. Playwright hỗ trợ điều này thông qua các trường usernamepassword trong đối tượng proxy.

JavaScript

const browser = await chromium.launch({
  proxy: {
    server: 'http://gate.proxyprovider.com:7777',
    username: 'your_login',
    password: 'your_password'
  }
});

Python

browser = p.chromium.launch(
    proxy={
        "server": "http://gate.proxyprovider.com:7777",
        "username": "your_login",
        "password": "your_password"
    }
)

Bạn cũng có thể truyền tên đăng nhập và mật khẩu trực tiếp trong URL của máy chủ proxy - điều này thuận tiện nếu bạn tạo chuỗi một cách động:

# Xác thực trong URL (Python)
proxy_url = f"http://{login}:{password}@gate.proxyprovider.com:7777"

browser = p.chromium.launch(
    proxy={"server": proxy_url}
)

⚠️ Cảnh báo

Không lưu trữ tên đăng nhập và mật khẩu của proxy trực tiếp trong mã! Sử dụng biến môi trường (os.environ trong Python hoặc process.env trong Node.js) hoặc tệp .env với thư viện dotenv.

Lưu trữ an toàn qua .env (Python)

import os
from dotenv import load_dotenv
from playwright.sync_api import sync_playwright

load_dotenv()

PROXY_SERVER   = os.getenv("PROXY_SERVER")
PROXY_LOGIN    = os.getenv("PROXY_LOGIN")
PROXY_PASSWORD = os.getenv("PROXY_PASSWORD")

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server":   PROXY_SERVER,
            "username": PROXY_LOGIN,
            "password": PROXY_PASSWORD
        }
    )
    # ...

Xoay vòng proxy: thay đổi IP cho mỗi yêu cầu

Một proxy không thể cứu bạn khỏi việc bị chặn khi có khối lượng yêu cầu lớn. Đối với việc thu thập dữ liệu nghiêm túc, cần phải có xoay vòng IP - tự động thay đổi máy chủ proxy sau các khoảng thời gian nhất định hoặc cho mỗi yêu cầu mới.

Có hai cách tiếp cận để xoay vòng trong Playwright:

Cách tiếp cận 1: Điểm cuối proxy xoay vòng

Hầu hết các nhà cung cấp proxy residential cung cấp một địa chỉ gateway duy nhất, tự động thay đổi IP khi mỗi lần kết nối. Bạn không cần phải viết logic xoay vòng - nó đã được tích hợp ở phía nhà cung cấp.

# Một điểm cuối - IP mới khi mỗi lần kết nối trình duyệt
browser = p.chromium.launch(
    proxy={
        "server":   "http://rotating.proxyprovider.com:8888",
        "username": "your_login",
        "password": "your_password"
    }
)

Cách tiếp cận 2: Xoay vòng thủ công qua danh sách proxy

Nếu bạn có danh sách proxy tĩnh, bạn có thể thực hiện việc xoay vòng một cách thủ công - tạo một trình duyệt mới hoặc ngữ cảnh cho mỗi lần lặp:

import random
from playwright.sync_api import sync_playwright

PROXY_LIST = [
    {"server": "http://proxy1.example.com:8080", "username": "user", "password": "pass"},
    {"server": "http://proxy2.example.com:8080", "username": "user", "password": "pass"},
    {"server": "http://proxy3.example.com:8080", "username": "user", "password": "pass"},
]

URLS_TO_SCRAPE = [
    "https://example.com/page1",
    "https://example.com/page2",
    "https://example.com/page3",
]

with sync_playwright() as p:
    for url in URLS_TO_SCRAPE:
        proxy = random.choice(PROXY_LIST)  # proxy ngẫu nhiên
        
        browser = p.chromium.launch(proxy=proxy)
        page = browser.new_page()
        
        page.goto(url)
        # ... thu thập dữ liệu ...
        
        browser.close()  # đóng trình duyệt, thay đổi IP

Cách tiếp cận 3: Xoay vòng qua BrowserContext (không cần khởi động lại trình duyệt)

with sync_playwright() as p:
    browser = p.chromium.launch()  # trình duyệt không có proxy
    
    for i, url in enumerate(URLS_TO_SCRAPE):
        proxy = PROXY_LIST[i % len(PROXY_LIST)]  # theo vòng
        
        # Ngữ cảnh mới với proxy mới - nhanh hơn so với khởi động lại trình duyệt
        context = browser.new_context(proxy=proxy)
        page = context.new_page()
        
        page.goto(url)
        # ... thu thập dữ liệu ...
        
        context.close()  # đóng ngữ cảnh, không phải trình duyệt
    
    browser.close()

Cách tiếp cận thứ ba - là hiệu quả nhất cho việc thu thập dữ liệu hàng loạt. Khởi động lại trình duyệt mất 2–4 giây, trong khi việc tạo ngữ cảnh mới mất chưa đến 100 mili giây.

Proxy ở cấp độ ngữ cảnh và trang

Playwright hỗ trợ kiến trúc linh hoạt: một trình duyệt có thể có nhiều ngữ cảnh cách ly, mỗi ngữ cảnh với proxy riêng. Điều này cho phép làm việc song song với nhiều IP trong cùng một quá trình.

Nhiều ngữ cảnh với các proxy khác nhau (thu thập dữ liệu song song)

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

(async () => {
  const browser = await chromium.launch();

  // Ngữ cảnh 1 - proxy từ Đức
  const context_de = await browser.newContext({
    proxy: {
      server: 'http://de-proxy.example.com:8080',
      username: 'user',
      password: 'pass'
    }
  });

  // Ngữ cảnh 2 - proxy từ Mỹ
  const context_us = await browser.newContext({
    proxy: {
      server: 'http://us-proxy.example.com:8080',
      username: 'user',
      password: 'pass'
    }
  });

  const page_de = await context_de.newPage();
  const page_us = await context_us.newPage();

  // Khởi động song song
  await Promise.all([
    page_de.goto('https://example.com'),
    page_us.goto('https://example.com')
  ]);

  // Cả hai trang đều thấy các IP khác nhau
  console.log('DE IP:', await page_de.textContent('body'));
  console.log('US IP:', await page_us.textContent('body'));

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

Cách tiếp cận này hoàn hảo cho việc kiểm thử định vị địa lý: bạn kiểm tra đồng thời cách mà trang web hiển thị cho người dùng từ các quốc gia khác nhau mà không cần khởi động nhiều phiên bản trình duyệt.

💡 Mẹo về hiệu suất

Để đạt được tính song song tối đa, hãy sử dụng asyncio trong Python hoặc Promise.all trong Node.js. Một trình duyệt có thể giữ 10–20 ngữ cảnh song song mà không gây tải nặng cho bộ nhớ.

Vượt qua bảo vệ chống bot: Cloudflare, Akamai, DataDome

Proxy chỉ là một phần của giải pháp. Các hệ thống chống bot hiện đại phân tích hàng chục tín hiệu cùng một lúc: fingerprint của trình duyệt, hành vi chuột, tốc độ điền biểu mẫu, tiêu đề HTTP và nhiều thứ khác. Ngay cả với proxy tốt, bạn vẫn có thể bị chặn nếu không xem xét các yếu tố này.

1. Ngụy trang chế độ headless

Playwright ở chế độ headless có những dấu hiệu đặc trưng dễ nhận diện: giá trị navigator.webdriver cụ thể, không có plugin, kích thước màn hình không chuẩn. Sử dụng thư viện playwright-stealth để ngụy trang:

# Python: cài đặt
# pip install playwright-stealth

from playwright.sync_api import sync_playwright
from playwright_stealth import stealth_sync

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server":   "http://residential.proxyprovider.com:8888",
            "username": "user",
            "password": "pass"
        }
    )
    page = browser.new_page()
    stealth_sync(page)  # áp dụng ngụy trang
    
    page.goto("https://bot.sannysoft.com")  # kiểm tra xác định bot
    browser.close()

2. User-Agent và viewport thực tế

context = browser.new_context(
    proxy={
        "server":   "http://proxy.example.com:8080",
        "username": "user",
        "password": "pass"
    },
    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",
    viewport={"width": 1920, "height": 1080},
    locale="ru-RU",
    timezone_id="Europe/Moscow"  # phải trùng với vị trí địa lý của proxy!
)

3. Giả lập hành vi con người

import time
import random

# Độ trễ ngẫu nhiên giữa các hành động
def human_delay(min_ms=500, max_ms=2000):
    time.sleep(random.randint(min_ms, max_ms) / 1000)

page.goto("https://example.com")
human_delay()

# Cuộn mượt mà thay vì ngay lập tức
page.evaluate("window.scrollBy({top: 500, behavior: 'smooth'})")
human_delay(300, 800)

# Di chuyển chuột trước khi nhấp
page.mouse.move(100, 200)
human_delay(100, 300)
page.mouse.move(300, 400)
human_delay(100, 200)
page.click("button#submit")

4. Khớp múi giờ với vị trí địa lý của proxy

Điều này thường bị bỏ qua, nhưng các hệ thống chống bot kiểm tra sự phù hợp: nếu proxy của bạn từ Moscow, nhưng trình duyệt hiển thị múi giờ UTC-8 (Los Angeles) - đó là một cờ đỏ. Luôn luôn thiết lập timezone_id theo vị trí địa lý của proxy đang sử dụng.

Các lỗi điển hình và cách khắc phục

Khi làm việc với proxy trong Playwright, các nhà phát triển thường gặp phải những vấn đề giống nhau. Chúng ta sẽ phân tích từng vấn đề với giải pháp cụ thể.

Lỗi 1: ERR_PROXY_CONNECTION_FAILED

Nguyên nhân: Địa chỉ hoặc cổng proxy không đúng, proxy không khả dụng, thông tin đăng nhập không đúng.
Giải pháp: Kiểm tra tính khả dụng của proxy qua curl trước khi khởi động Playwright:

# Kiểm tra proxy qua curl
curl -x http://user:[email protected]:8080 https://api.ipify.org

Lỗi 2: SOCKS5 không chấp nhận xác thực

Nguyên nhân: Playwright (Chromium) có hỗ trợ hạn chế SOCKS5 với xác thực qua username/password.
Giải pháp: Sử dụng proxy HTTP với xác thực hoặc thiết lập một tunnel SOCKS5 cục bộ qua ssh -D mà không cần mật khẩu.

Lỗi 3: Proxy hoạt động nhưng trang vẫn chặn

Nguyên nhân: Sử dụng proxy data-center, nằm trong danh sách đen; chế độ headless không được ngụy trang; tần suất yêu cầu quá cao.
Giải pháp: Chuyển sang proxy residential hoặc mobile, thêm playwright-stealth, tăng độ trễ giữa các yêu cầu.

Lỗi 4: Rò rỉ IP thực (DNS leak)

Nguyên nhân: Các yêu cầu DNS có thể đi qua proxy.
Giải pháp: Playwright theo mặc định chuyển DNS qua proxy khi sử dụng proxy HTTP. Nhưng để kiểm tra, hãy sử dụng https://dnsleaktest.com trong trình duyệt headless.

Lỗi 5: Hoạt động chậm với proxy

Nguyên nhân: Proxy residential chậm hơn proxy data-center; khoảng cách lớn đến máy chủ proxy.
Giải pháp: Chọn proxy ở các vị trí địa lý gần. Đối với các nhiệm vụ không yêu cầu nghiêm ngặt về ẩn danh, hãy sử dụng proxy data-center - chúng nhanh hơn nhiều.

Lỗi Giải pháp nhanh
ERR_PROXY_CONNECTION_FAILED Kiểm tra curl, tên đăng nhập/mật khẩu, tính khả dụng của cổng
407 Proxy Auth Required Thêm tên đăng nhập và mật khẩu vào cấu hình proxy
Trang hiển thị CAPTCHA Thay đổi loại proxy sang residential, thêm stealth
IP không thay đổi khi xoay vòng Đóng ngữ cảnh/trình duyệt giữa các yêu cầu
Thời gian kết nối quá lâu Tăng timeout trong goto(), chọn proxy gần hơn

Kết luận và khuyến nghị

Cấu hình proxy trong Playwright không phải là một nhiệm vụ đơn lẻ, mà là một phần của kiến trúc công cụ tự động hóa của bạn. Loại proxy được chọn đúng cách, xoay vòng IP hợp lý và ngụy trang chế độ headless cùng nhau tạo ra sự ổn định ngay cả trên các trang web có bảo vệ chống bot nghiêm ngặt.

Tóm tắt về việc chọn loại proxy cho các nhiệm vụ cụ thể:

  • Thu thập dữ liệu công khai không có bảo vệ nghiêm ngặt - proxy data-center nhanh sẽ phù hợp.
  • Chợ trực tuyến (Wildberries, Ozon), các tập hợp tin tức - cần proxy residential với xoay vòng.
  • Mạng xã hội (Instagram, Facebook, TikTok) và các trang web với Cloudflare - chỉ proxy mobile hoặc residential.
  • Kiểm thử định vị địa lý - bất kỳ loại proxy nào ở quốc gia cần thiết, điều quan trọng là khớp múi giờ.
  • Thu thập dữ liệu hàng loạt với tần suất cao - proxy residential xoay vòng với điểm cuối gateway.

Nếu bạn đang xây dựng hệ thống thu thập dữ liệu hoặc kiểm thử tự động trên Playwright và cần hoạt động ổn định mà không bị chặn, chúng tôi khuyên bạn nên xem xét proxy residential - chúng cung cấp mức độ tin cậy cao từ các trang web và hỗ trợ xoay vòng IP qua một điểm cuối duy nhất, điều này đơn giản hóa việc tích hợp với Playwright chỉ còn vài dòng mã.

```