Cách vượt qua Cloudflare
Trong bài viết này, bạn sẽ học cách vượt qua trang "Verifying you are human" của Cloudflare bằng NodeJS với tự động hóa trình duyệt Playwright.

Trước tiên, hãy cùng tìm hiểu ngắn gọn về cách Cloudflare hoạt động. Không có Cloudflare, quản trị viên website sẽ lưu trữ các trang của họ trên máy chủ có địa chỉ IP công khai. Tên miền được trỏ đến IP đó và trình duyệt của bạn kết nối trực tiếp với máy chủ.
Khi họ sử dụng Cloudflare, họ ủy quyền việc quản lý DNS cho Cloudflare, đơn vị sẽ trỏ tên miền đến các địa chỉ IP của riêng họ. Trên các IP này, họ chạy các máy chủ proxy đặc biệt để lọc các yêu cầu HTTP và HTTPS đến.
Khách truy cập mới sẽ thấy trang nổi tiếng với dòng chữ: "Verifying you are human. This may take a few seconds.". Trong quá trình xác minh, bạn có thể phải giải một captcha. Trước đây họ sử dụng reCAPTCHA, nhưng giờ họ đã dùng captcha riêng của họ có tên là Turnstile.
Khi vượt qua xác minh captcha, trình duyệt sẽ nhận được một mã token duy nhất trong cookie có tên cf_clearance. Trình duyệt của bạn sẽ dùng token này để gửi yêu cầu tải trang từ proxy của Cloudflare. Nếu token này hết hạn hoặc Cloudflare phát hiện nó có hành vi giống bot, nó sẽ bị vô hiệu hóa và bạn sẽ lại thấy trang xác minh.
Phương pháp của chúng tôi giúp bạn lấy token đó bằng một phiên trình duyệt tự động. Lưu ý rằng phương pháp này không tiết lộ địa chỉ IP thực sự của website — chỉ Cloudflare và quản trị viên trang web mới biết được thông tin đó. Và điều đó là tốt!
Đây là cách thực hiện bằng NodeJS và Playwright:
// Install packages
// npx install playwright @antiadmin/anticaptchaofficial
import { chromium } from "playwright";
import ac from "@antiadmin/anticaptchaofficial";
// Specify the target website address
const websiteBehindCloudFlare = 'https://yourwebsite.com';
// Set your Anti-Captcha API key here:
ac.setAPIKey('API_KEY_HERE');
ac.setSoftId(0);
let browser = null;
let page = null;
(async () => {
// Opening the browser
try {
console.log('Opening browser ..');
browser = await chromium.launch({ headless: false });
console.log('Creating new page ..');
page = await browser.newPage();
} catch (e) {
console.log("Could not open browser: "+e.toString());
return;
}
let params = null;
try {
// Doing several attempts to inject our code
while (!params) {
console.log('Navigating to the page')
await page.goto(websiteBehindCloudFlare);
console.log('Injecting our proxy code to replace window.turnstile');
await page.evaluate(() => {
window.turnstile = new Proxy(window.turnstile, {
get(target, prop) {
if (prop === "render") {
return function (a, b) {
const p = {
websiteURL: window.location.href,
websiteKey: b.sitekey,
action: b.action,
cData: b.cData,
chlPageData: b.chlPageData,
userAgent: navigator.userAgent,
};
// saving params in window.params
window.params = p;
// assigning callback to a variable
window.cfCallback = b.callback
// calling original render function
return target.render.apply(this, arguments);
};
}
return target[prop];
},
});
});
console.log('Getting params');
params = await page.evaluate(() => {
return new Promise((resolve) => {
setTimeout(() => resolve(window.params || null), 5000);
});
});
if (!params) {
console.log('Retrying..');
await delay(3000);
}
}
console.log("Extracted Turnstile Params:", params);
console.log('Solving Turnstile captcha with Anti-Captcha')
const token = await ac.solveTurnstileProxyless(websiteBehindCloudFlare, params.websiteKey, params.action, params.cData, params.chlPageData);
// Running Cloudflare's callback function we previously assigned to window.cfCallback
await page.evaluate((token) => {
window.cfCallback(token)
}, token);
console.log('Waiting for redirects to finish')
await delay(5000);
// Get all cookies for current page
const cookies = await page.context().cookies();
// Find cf_clearance
const cf_clearance = cookies.filter(c => c.name === 'cf_clearance');
// Output cookies
console.log('Cookies:', cookies);
console.log('cf_clearance:', cf_clearance);
} catch (e) {
console.error('Could not inject proxy code:', e);
}
// close browser when needed
// await browser.close();
})();
function delay(time) {
return new Promise(function(resolve) {
setTimeout(resolve, time)
});
}
Những gì đoạn mã của chúng tôi làm:
1. Mở cửa sổ trình duyệt và điều hướng đến trang xác minh Cloudflare.
2. Ghi đè hàm render của Turnstile bằng hàm proxy của chúng tôi, trong đó chúng tôi chặn các tham số khởi tạo và hàm callback khi captcha được giải.
3. Gửi tham số khởi tạo đến API Anti-Captcha. Nhân viên con người sẽ giải captcha cho bạn và trả lại một token.
4. Gọi lại hàm callback đã lưu trước đó với token Turnstile làm tham số.
5. Cloudflare xác minh token nội bộ, đặt cookie vào trình duyệt và tải lại trang.
6. Với cf_clearance này, trình duyệt sẽ truy xuất nội dung của website thông qua proxy Cloudflare.