
Anh Tuan
Data Science Expert

Playwright là một khung kiểm thử tự động hóa trình duyệt hiện đại được phát triển bởi Microsoft. Nó hỗ trợ tự động hóa cho Chromium, Firefox và WebKit (tương ứng với Chrome, Firefox và Safari). Nó cung cấp một API mạnh mẽ để điều khiển trình duyệt, lựa chọn phần tử, tương tác biểu mẫu, chặn mạng và hơn thế nữa — làm cho nó lý tưởng cho các tác vụ yêu cầu tương tác sâu sắc với các trang web.
Bất kỳ trình duyệt nào, bất kỳ nền tảng nào, một API
Sử dụng Playwright trong Node.js:
npm i playwright
npx playwright install # Cài đặt tất cả các trình duyệt (Chromium, Firefox, WebKit)
Ví dụ: Lấy tất cả tiêu đề blog từ CapSolver
Trong ví dụ bên dưới, chúng ta sử dụng Playwirght để điều hướng đến blog CapSolver và lấy tất cả tiêu đề bài đăng blog <h5> từ trang

const { chromium } = require('playwright');
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
});
const [page] = context.pages();
await page.goto('https://www.capsolver.com/blog/All');
const h5Titles = await page.evaluate(() => {
const headings = Array.from(document.querySelectorAll('h5'));
return headings.map(heading => heading.textContent.trim());
});
console.log(h5Titles);
await context.close();
})();
Playwright đủ mạnh để tải các tiện ích mở rộng trình duyệt giống như một trình duyệt thông thường.
--disable-extensions-except và --load-extension.const { chromium } = require('playwright');
const extensionPath = 'path/to/capsolver extension';
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: [
`--disable-extensions-except=${extensionPath}`,
`--load-extension=${extensionPath}`,
],
});
const [page] = context.pages();
await page.goto('https://www.capsolver.com/blog/All');
await browser.close();
})();
Các loại CAPTCHA như reCAPTCHA v2/v3, Cloudflare Turnstile, AWS WAF, được sử dụng rộng rãi trên hàng nghìn trang web. Mặc dù phổ biến, nhưng các CAPTCHA này thường có cấu trúc DOM nhất quán và có thể phát hiện được. Đó là nơi Tiện ích mở rộng CapSolver hoạt động — nó tự động phát hiện và giải quyết chúng mà không cần tương tác thủ công.
Hãy lấy reCAPTCHA v2 làm ví dụ để chứng minh cách giải quyết nó bằng Tiện ích mở rộng CapSolver trong Playwright.
Lưu ý: Trừ khi được nêu rõ, các ví dụ sau đây sử dụng chế độ nhấp (/assets/config.js -> reCaptchaMode: 'click').
⚠️ Đừng quên giải nén tệp zip tiện ích mở rộng và cấu hình
apiKeycủa bạn trong/assets/config.js
const { chromium } = require('playwright');
// Bước 1: Tải xuống tiện ích mở rộng từ GitHub: https://github.com/capsolver/capsolver-browser-extension/releases
// Bước 2: Giải nén tệp tiện ích mở rộng và đặt apiKey của bạn trong /assets/config.js
const extensionPath = 'path/to/CapSolver Browser Extension-v1.16.0';
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: [
`--disable-extensions-except=${extensionPath}`,
`--load-extension=${extensionPath}`,
'--lang=en-US'
],
});
const [page] = context.pages();
await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
await page.waitForSelector('form[action="/recaptcha-v2-checkbox.php"]');
// Tiện ích mở rộng sẽ tự động phát hiện và giải quyết reCAPTCHA.
await page.waitForTimeout(15000); // Chờ giải quyết
await page.click('button[type="submit"]');
await page.waitForTimeout(5000);
await context.close();
})();
⚠️ Tiện ích mở rộng CapSolver cũng hỗ trợ nhiều tùy chọn cấu hình hữu ích. Dưới đây là một số ví dụ phổ biến (Lưu ý: Tất cả các cấu hình được đặt trong
/assets/config.js)
solvedCallbackNhư bạn có thể đã nhận thấy, trong mã trước đó, chúng tôi đã chờ 15 giây sau khi tải trang trước khi nhấp vào nút gửi. Sự chậm trễ này nhằm mục đích cung cấp cho tiện ích mở rộng CapSolver đủ thời gian để tự động giải quyết reCAPTCHA. Tuy nhiên, cách tiếp cận này không lý tưởng — đôi khi CAPTCHA được giải quyết nhanh hơn nhiều và trong điều kiện mạng kém, nó có thể mất nhiều hơn 15 giây.
Đó là nơi solvedCallback hoạt động. Nó cung cấp một giải pháp tốt hơn bằng cách kích hoạt một hàm gọi lại khi CAPTCHA đã được giải quyết, thông báo cho bạn rằng xác minh đã hoàn tất. Bạn có thể cấu hình solvedCallback trong /assets/config.js bằng cách định nghĩa tên hàm tùy chỉnh — theo mặc định, đó là captchaSolvedCallback. Sau đó, hãy sử dụng page.exposeFunction trong Playwright để hiển thị hàm này trong ngữ cảnh trình duyệt.
Bây giờ, hãy cải thiện mã trước đó của chúng ta bằng cách tiếp cận này.
const { chromium } = require('playwright');
const extensionPath = 'path/to/CapSolver Browser Extension-v1.16.0';
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: [
`--disable-extensions-except=${extensionPath}`,
`--load-extension=${extensionPath}`,
'--lang=en-US'
],
});
const [page] = context.pages();
await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
await page.waitForSelector('form[action="/recaptcha-v2-checkbox.php"]');
await page.exposeFunction('captchaSolvedCallback', async () => {
console.log('Captcha đã được giải quyết!');
const iframe = await page.$('iframe[src*="recaptcha"]');
if (iframe) {
const frame = await iframe.contentFrame();
const finished = await frame.evaluate(() => {
const element = document.querySelector('.recaptcha-checkbox-border');
return element && window.getComputedStyle(element).display === 'none';
});
if (finished) {
console.log('Xác minh đã hoàn tất!');
await page.click('button[type="submit"]');
await page.waitForTimeout(3000);
await context.close();
} else {
console.log('Xác minh chưa hoàn tất. Thử lại...');
}
}
});
})();
Đối với reCAPTCHA v2, đôi khi nhiều thử thách hình ảnh có thể xuất hiện. Vì vậy, sau mỗi thử thách, chúng ta kiểm tra xem hộp kiểm "Tôi không phải là người máy" đã được chọn chưa — nếu nó biến mất, quá trình xác minh được coi là đã hoàn tất.
manualSolvingTrong các ví dụ trước đó, việc giải quyết CAPTCHA bắt đầu ngay lập tức khi tải trang. Tuy nhiên, trong một số trường hợp, bạn có thể cần thực hiện các tác vụ khác trước tiên — như nhập tên người dùng/mật khẩu — trước khi kích hoạt việc giải quyết CAPTCHA. Bắt đầu quá sớm có thể khiến mã thông báo hết hạn.
Để xử lý điều này, hãy đặt manualSolving: true trong /assets/config.js, cho phép bạn tự động kích hoạt quá trình giải quyết CAPTCHA.
Có hai cách để kích hoạt giải quyết:
window.postMessage({ type: 'capsolverSolve' });⚠️ Lưu ý: Tính năng này chỉ được hỗ trợ trong các phiên bản tiện ích mở rộng cao hơn v1.16.0!
Ví dụ:
const { chromium } = require('playwright');
const extensionPath = 'path/to/CapSolver Browser Extension-v1.16.0';
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: [
`--disable-extensions-except=${extensionPath}`,
`--load-extension=${extensionPath}`,
'--lang=en-US'
],
});
const [page] = context.pages();
await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
await page.waitForSelector('form[action="/recaptcha-v2-checkbox.php"]');
// Mô phỏng việc điền thông tin đăng nhập
await page.evaluate(() => {
const inputA = document.querySelector('input[name="ex-a"]');
inputA.value = 'username';
const inputB = document.querySelector('input[name="ex-b"]');
inputB.value = 'password';
});
// Mô phỏng các sự chậm trễ hoặc hoạt động của người dùng khác
for (let i = 1; i <= 5; i++) {
await page.waitForTimeout(1000);
console.log(`Đã chờ ${i} giây...`);
}
console.log('Bắt đầu giải quyết CAPTCHA...');
// Phương pháp 1: Mô phỏng việc nhấp vào nút CapSolver
await page.evaluate(() => {
document.querySelector('#capsolver-solver-tip-button').click();
});
// Phương pháp 2: Kích hoạt bằng postMessage
// await page.evaluate(() => {
// window.postMessage({ type: 'capsolverSolve' });
// });
await page.exposeFunction('captchaSolvedCallback', async () => {
console.log('Captcha đã được giải quyết!');
const iframe = await page.$('iframe[src*="recaptcha"]');
if (iframe) {
const frame = await iframe.contentFrame();
const finished = await frame.evaluate(() => {
const element = document.querySelector('.recaptcha-checkbox-border');
return element && window.getComputedStyle(element).display === 'none';
});
if (finished) {
console.log('Xác minh đã hoàn tất!');
await page.click('button[type="submit"]');
await page.waitForTimeout(3000);
await context.close();
} else {
console.log('Xác minh chưa hoàn tất. Thử lại.');
}
}
});
})();
reCaptchaModeCài đặt reCaptchaMode hỗ trợ hai chế độ: click và token.
Nếu bạn gặp phải nhiều vòng lựa chọn hình ảnh bằng chế độ click, có thể là do điểm dấu vân tay trình duyệt thấp. Nên chuyển sang chế độ token để có độ tin cậy tốt hơn.
| Chế độ Click | Chế độ Token |
|---|---|
![]() |
![]() |
showSolveButtonKhi showSolveButton được đặt thành false (mặc định là true), nút CapSolver sẽ không còn được hiển thị trên trang nữa. Tuy nhiên, điều này sẽ không ảnh hưởng đến chức năng giải quyết CAPTCHA bình thường.

Sau khi đặt useProxy: true, bạn có thể chỉ định các tham số sau: proxyType, hostOrIp, port, proxyLogin và proxyPassword. Với thiết lập này, chúng ta sẽ sử dụng proxy tùy chỉnh của bạn để giải quyết CAPTCHA. Khi nào bạn nên sử dụng proxy của riêng mình? Thông thường, trong các trường hợp sau:
Trên đây là một số tùy chọn cấu hình thường được sử dụng. Bạn có thể điều chỉnh các cài đặt khác theo nhu cầu thực tế của mình. Nếu bạn có bất kỳ câu hỏi nào, vui lòng liên hệ với hỗ trợ khách hàng của chúng tôi.
Không giống như các CAPTCHA của bên thứ ba như reCAPTCHA, Cloudflare Turnstile, AWS WAF hoặc GeeTest, có một loại CAPTCHA khác yêu cầu nhận dạng chữ cái hoặc chữ số từ hình ảnh. Chúng tôi gọi đây là CAPTCHA ImageToText. Chúng thường trông như thế này:

ImageToText là một CAPTCHA được chính quản trị viên trang web triển khai. Không giống như CAPTCHA của bên thứ ba, CAPTCHA ImageToText được chủ sở hữu trang web tùy chỉnh. Vì các CAPTCHA này khác nhau về vị trí trên các trang web và trang khác nhau, nên Tiện ích mở rộng CapSolver không thể tự động phát hiện hình ảnh nào là CAPTCHA. Do đó, bạn phải thông báo rõ ràng cho Tiện ích mở rộng CapSolver trong mã của mình. Đây là cách thực hiện:
capsolver-image-to-text-source có giá trị 0 vào phần tử hình ảnh của CAPTCHA;capsolver-image-to-text-result có giá trị 0 vào trường nhập nơi kết quả nên được điền vào.Các thuộc tính này — capsolver-image-to-text-source và capsolver-image-to-text-result — có thể được cấu hình trong /assets/config.js bằng các trường textCaptchaSourceAttribute và textCaptchaResultAttribute, tương ứng.
Hãy cùng xem xét một ví dụ sử dụng trang:
https://captcha.com/demos/features/captcha-demo.aspx
Đầu tiên, hãy kiểm tra nguồn trang để định vị phần tử hình ảnh CAPTCHA và trường nhập kết quả. Trong trường hợp này:
demoCaptcha_CaptchaImagecaptchaCodeBây giờ, chúng ta hãy sử dụng Playwright để tự động giải quyết CAPTCHA này bằng cách đánh dấu các phần tử này cho phù hợp:
const { chromium } = require('playwright');
// Bước 1: Lấy tiện ích mở rộng từ GitHub (https://github.com/capsolver/capsolver-browser-extension/releases)
// Bước 2: Giải nén tệp zip tiện ích mở rộng và cấu hình apiKey của bạn trong /assets/config.js
const extensionPath = 'path/to/CapSolver Browser Extension-v1.16.0';
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: [
`--disable-extensions-except=${extensionPath}`,
`--load-extension=${extensionPath}`,
'--lang=en-US'
],
});
const [page] = context.pages();
await page.goto('https://captcha.com/demos/features/captcha-demo.aspx');
await page.waitForSelector('#demoCaptcha_CaptchaImage');
// Thông báo cho Tiện ích mở rộng CapSolver vị trí của hình ảnh CAPTCHA
await page.evaluate(() => {
const imgElement = document.querySelector('#demoCaptcha_CaptchaImage');
if (imgElement) {
imgElement.setAttribute('capsolver-image-to-text-source', '0');
}
});
// Thông báo cho Tiện ích mở rộng CapSolver vị trí kết quả nhận dạng nên được nhập
await page.evaluate(() => {
const resultElement = document.querySelector('#captchaCode');
if (resultElement) {
resultElement.setAttribute('capsolver-image-to-text-result', '0');
}
});
// Chờ CAPTCHA được giải quyết và gửi biểu mẫu
await page.exposeFunction('captchaSolvedCallback', async () => {
console.log('Captcha đã được giải quyết!');
await page.waitForTimeout(3000);
await page.click('#validateCaptchaButton');
await page.waitForTimeout(3000);
await context.close();
});
})();
Kết quả:

Sử dụng Tiện ích mở rộng CapSolver rất tiện lợi và nhanh chóng, nhưng nếu bạn là một nhà phát triển giàu kinh nghiệm, chúng tôi khuyến khích bạn nên sử dụng tích hợp API hơn. So với phương pháp dựa trên tiện ích mở rộng, phương pháp API cung cấp một số lợi thế chính:
Trước khi chúng ta đi sâu vào bản demo mã, đây là tổng quan nhanh về cách sử dụng API CapSolver:
Để tạo một tác vụ, bạn cần gửi một đối tượng JSON đến CapSolver. JSON này bao gồm clientKey, websiteURL, websiteKey và các dữ liệu khác của bạn. Các trường này thay đổi tùy thuộc vào loại CAPTCHA và trang web.
👉 Để biết chi tiết, hãy tham khảo tài liệu của chúng tôi: tài liệu
Trước khi giải quyết reCAPTCHA v2, vui lòng đọc tài liệu tại đây:
📖 ReCaptchaV2
Hướng dẫn này giải thích các tham số JSON cần bao gồm khi tạo một tác vụ.
Ngoài ra, bạn có thể sử dụng Tiện ích mở rộng CapSolver để nhanh chóng tạo dữ liệu JSON cho các yêu cầu API của mình.
Xem blog này để được trợ giúp:
🔗 lấy dữ liệu JSON
Hãy lấy ví dụ sau:
🔗 https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php
JSON cần thiết để tạo một tác vụ cho trang này là:
{
"type": "ReCaptchaV2TaskProxyLess",
"websiteKey": "6LfW6wATAAAAAHLqO2pb8bDBahxlMxNdo9g947u9",
"websiteURL": "https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php"
}
Chúng tôi cũng cung cấp các mẫu mã JavaScript để sử dụng API trong tài liệu của mình:

Tích hợp trong Playwright:
const { chromium } = require('playwright');
const axios = require('axios');
// Thay thế bằng khóa API của bạn
const api_key = 'YOUR_API_KEY';
const captcha_type = 'ReCaptchaV2TaskProxyLess';
const site_key = '6LfW6wATAAAAAHLqO2pb8bDBahxlMxNdo9g947u9';
const site_url = 'https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php';
async function capSolver() {
const payload = {
clientKey: api_key,
task: {
type: captcha_type,
websiteKey: site_key,
websiteURL: site_url
}
};
try {
const res = await axios.post('https://api.capsolver.com/createTask', payload);
const task_id = res.data.taskId;
if (!task_id) {
console.log('Thất bại khi tạo tác vụ:', res.data);
return;
}
console.log('Đã lấy taskId:', task_id);
while (true) {
await new Promise(resolve => setTimeout(resolve, 1000)); // Chờ trong 1 giây
const getResultPayload = { clientKey: api_key, taskId: task_id };
const resp = await axios.post('https://api.capsolver.com/getTaskResult', getResultPayload);
const status = resp.data.status;
if (status === 'ready') {
return resp.data.solution.gRecaptchaResponse;
}
if (status === 'failed' || resp.data.errorId) {
console.log('Giải quyết thất bại! phản hồi:', resp.data);
return;
}
}
} catch (error) {
console.error('Lỗi:', error);
}
}
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: ['--lang=en-US'],
});
const [page] = context.pages();
await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
await page.waitForSelector('form[action="/recaptcha-v2-checkbox.php"]');
const token = await capSolver();
console.log("Token:", token);
// Đặt giá trị token
await page.evaluate((token) => {
const textarea = document.getElementById('g-recaptcha-response');
if (textarea) {
textarea.value = token;
}
}, token);
await page.click('button[type="submit"]');
await page.waitForTimeout(5000);
await context.close();
})();
Chúng ta vẫn sử dụng ví dụ về https://captcha.com/demos/features/captcha-demo.aspx, trong đó phần tử hình ảnh captcha có id demoCaptcha_CaptchaImage, và phần tử đầu vào kết quả có id captchaCode, như được hiển thị trong hình ảnh sau:

Đối với ImageToTextTask, chúng ta cần truyền giá trị base64 của hình ảnh captcha đến CapSolver. Mã ví dụ như sau:
const { chromium } = require('playwright');
const axios = require('axios');
// Thay thế bằng khóa API của bạn
const api_key = 'YOUR_API_KEY';
const captcha_type = 'ImageToTextTask';
const site_url = 'https://captcha.com/demos/features/captcha-demo.aspx';
async function capSolver(base64Image) {
const payload = {
clientKey: api_key,
task: {
type: captcha_type,
websiteURL: site_url,
body: base64Image,
}
};
try {
const res = await axios.post('https://api.capsolver.com/createTask', payload);
const status = res.data.status;
if (status === 'ready') {
return res.data.solution.text;
}
if (status === 'failed' || res.data.errorId) {
console.log('Giải quyết thất bại! phản hồi:', res.data);
return "";
}
} catch (error) {
console.error('Lỗi:', error);
}
}
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: ['--lang=en-US'],
});
const [page] = context.pages();
await page.goto('https://captcha.com/demos/features/captcha-demo.aspx');
await page.waitForSelector('#demoCaptcha_CaptchaImage');
// Lấy giá trị base64 của hình ảnh captcha
const captchaImage = await page.evaluate(() => {
const img = document.querySelector('img[id="demoCaptcha_CaptchaImage"]');
return img ? img.getAttribute('src') : null;
});
const base64Image = captchaImage.split(',')[1];
const text = await capSolver(base64Image);
console.log("Text:", text);
// Đặt văn bản captcha đã được giải quyết
await page.evaluate((text) => {
document.getElementById('captchaCode').value = text;
}, text);
await page.click('#validateCaptchaButton');
await page.waitForTimeout(5000);
await context.close();
})();
Ngoài ra, đối với một số loại ImageToText đặc biệt, bạn có thể chỉ định các mô hình khác nhau để cải thiện độ chính xác. Để biết chi tiết, vui lòng tham khảo tài liệu của chúng tôi:
https://docs.capsolver.com/en/guide/recognition/ImageToTextTask/

Video demo có tính năng Tiện ích mở rộng CapSolver:
Ngoài ra, CapSolver cung cấp Chương trình chia sẻ doanh thu cho nhà phát triển, cho phép các nhà phát triển và đối tác kiếm hoa hồng bằng cách tích hợp hoặc quảng bá các giải pháp CapSolver. Đó là một cách tuyệt vời để kiếm tiền từ công việc của bạn đồng thời giúp người khác giải quyết các captcha một cách hiệu quả. Để biết đầy đủ chi tiết, hãy xem:
Kế hoạch dành cho nhà phát triển CapSolver
Các tính năng mạnh mẽ của Playwright, kết hợp với khả năng xử lý CAPTCHA của CapSolver, cung cấp một giải pháp toàn diện cho tự động hóa web. Cho dù sử dụng tiện ích mở rộng CapSolver để thuận tiện hay API để kiểm soát tốt hơn, việc tích hợp này sẽ hợp lý hóa các tác vụ phức tạp và nâng cao quy trình tự động hóa. Ngoài việc chỉ giải quyết CAPTCHA, hãy nhớ rằng CapSolver cũng cung cấp Chương trình chia sẻ doanh thu cho nhà phát triển, tạo cơ hội tuyệt vời để kiếm hoa hồng bằng cách tích hợp hoặc quảng bá các giải pháp của họ
Hướng dẫn Captcha cho quy trình dữ liệu được phê duyệt: học về các loại thách thức, xử lý API, tính nhất quán của proxy, lần thử lại và sử dụng có trách nhiệm.

API giải CAPTCHA nhanh chóng dành cho tự động hóa: so sánh quy trình token, các thách thức được hỗ trợ, kiểm tra độ trễ và tích hợp CapSolver có trách nhiệm.
