const express = require('express');
const puppeteer = require('puppeteer-extra');
puppeteer.use(require('puppeteer-extra-plugin-stealth')());
const path = require('path');
const app = express();
const port = process.env.PORT || 7860;
const HTML_TEMPLATE = `
Turnstile Solver
`;
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
async function solveTurnstile(url, sitekey) {
const browser = await puppeteer.launch({
headless: "new",
executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || null,
args: [
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-dev-shm-usage",
"--disable-blink-features=AutomationControlled"
]
});
try {
const page = await browser.newPage();
const urlFixed = url.endsWith("/") ? url : url + "/";
await page.setRequestInterception(true);
page.on('request', (req) => {
if (req.url() === urlFixed && req.resourceType() === 'document') {
const html = HTML_TEMPLATE.replace('id="turnstile-widget"', `id="turnstile-widget" data-sitekey="${sitekey}"`);
req.respond({ status: 200, contentType: 'text/html', body: html });
} else {
req.continue();
}
});
await page.goto(urlFixed, { waitUntil: 'domcontentloaded' });
// Tunggu iframe muncul dan klik jika perlu
await page.waitForSelector('.cf-turnstile', { timeout: 10000 });
await sleep(2000);
// Polling token
for (let i = 0; i < 30; i++) {
const token = await page.evaluate(() => window.capturedToken || null);
if (token) {
await browser.close();
return token;
}
await sleep(1000);
}
throw new Error("Timeout: Gagal mendapatkan token Turnstile");
} catch (err) {
await browser.close();
throw err;
}
}
app.get('/solve', async (req, res) => {
const { url, siteKey } = req.query;
if (!url || !siteKey) {
return res.status(400).json({ error: "Parameter 'url' dan 'siteKey' diperlukan" });
}
try {
console.log(`Menyelesaikan Turnstile untuk: ${url}`);
const token = await solveTurnstile(url, siteKey);
res.json({ result: token });
} catch (error) {
console.error(error);
res.status(500).json({ error: error.message });
}
});
app.get('/', (req, res) => {
res.send('Turnstile Solver API sedang berjalan. Gunakan endpoint /solve');
});
app.listen(port, () => {
console.log(`Server berjalan di port ${port}`);
});