Cloudflare をバイパスする方法
この記事では、NodeJS と Playwright ブラウザ自動化を使って Cloudflare の「あなたが人間であることを確認しています」ページをバイパスする方法を学びます。

まず、Cloudflare がどのように動作するのか簡単に理解しておきましょう。Cloudflare を使用していない場合、ウェブサイト管理者は自分のページをパブリック IP アドレスを持つサーバーにホストします。ドメイン名はその IP アドレスに解決され、ブラウザは直接そのサーバーに接続します。
Cloudflare を使用する場合、DNS の管理を Cloudflare に委任します。Cloudflare はそのドメイン名を自社の IP アドレスに解決し、そこで特殊なプロキシサーバーを動かして、HTTP や HTTPS のリクエストをフィルタリングします。
新しい訪問者には、次のような有名なページが表示されます:「Verifying you are human. This may take a few seconds.」。この検証の間、キャプチャの解決を求められる場合があります。以前は reCAPTCHA が使われていましたが、現在は自社製の Turnstile キャプチャが使用されています。
キャプチャの認証が成功すると、ブラウザは cf_clearance という名前のクッキーに一意のトークンを受け取ります。ブラウザはこのトークンを使用して、Cloudflare プロキシからウェブサイトのページをリクエストします。このトークンの有効期限が切れるか、Cloudflare がそのトークンの振る舞いをボットと判断すると、トークンは無効化され、再び検証画面が表示されます。
この方法により、自動化されたブラウザセッションを使用してそのトークンを取得できます。この方法では、ウェブサイトの本当の IP アドレスは明かされません — その情報は Cloudflare とウェブサイト管理者だけが知っています。そして、それは良いことです!
NodeJS と 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)
});
}
コードで行っていること:
1. ブラウザウィンドウを開いて、Cloudflare の検証ページにアクセスします。
2. Turnstile の render 関数を、初期化パラメータとキャプチャ完了時のコールバックを取得するプロキシ関数に置き換えます。
3. 初期化パラメータを Anti-Captcha API に送信します。人間の作業者がキャプチャを解決し、トークンを返してくれます。
4. 以前に保存したコールバック関数を、取得した Turnstile トークンを引数として呼び出します。
5. Cloudflare はそのトークンを内部で検証し、 クッキーをブラウザにセットし、ページをリロードします。
6. その cf_clearance により、ブラウザは Cloudflare プロキシ経由でウェブサイトのコンテンツを取得します。