const express = require('express') const { connect } = require("puppeteer-real-browser") const fs = require("fs") const path = require("path") const app = express() const port = process.env.PORT || 7860 const authToken = process.env.authToken || null const DOMAIN = process.env.DOMAIN || 'https://rezaharis-captcha.hf.space' global.browserLimit = Number(process.env.browserLimit) || 20 global.timeOut = Number(process.env.timeOut) || 60000 const CACHE_DIR = path.join(__dirname, "cache") const CACHE_FILE = path.join(CACHE_DIR, "cache.json") const CACHE_TTL = 5 * 60 * 1000 function loadCache() { if (!fs.existsSync(CACHE_FILE)) return {} try { return JSON.parse(fs.readFileSync(CACHE_FILE, "utf-8")) } catch { return {} } } function saveCache(cache) { if (!fs.existsSync(CACHE_DIR)) { fs.mkdirSync(CACHE_DIR, { recursive: true }) } fs.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8") } function readCache(key) { const cache = loadCache() const entry = cache[key] if (entry && Date.now() - entry.timestamp < CACHE_TTL) { return entry.value } return null } function writeCache(key, value) { const cache = loadCache() cache[key] = { timestamp: Date.now(), value } saveCache(cache) } app.use(express.json()) app.use(express.urlencoded({ extended: true })) app.get('/', (req, res) => { res.json({ status: "active", message: "Cloudflare Bypass API is running", endpoints: { "/cloudflare": "Solve Cloudflare challenges (turnstile/iuam)", "/cloudflare-cookies": "Bypass Cloudflare with cookies", "/turnstile": "Solve Turnstile captcha", "/recaptchav3": "Solve reCAPTCHA v3" }, usage: "curl -X POST https://your-app.hf.space/cloudflare-cookies -H 'Content-Type: application/json' -d '{\"domain\":\"https://example.com\",\"cookies\":[\"cookie1=value1\"]}'" }) }) async function createBrowser(proxyServer = null) { const connectOptions = { headless: true, turnstile: true, connectOption: { defaultViewport: { width: 1920, height: 1080 }, args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-accelerated-2d-canvas', '--no-first-run', '--no-zygote', '--disable-gpu' ] }, disableXvfb: false, } if (proxyServer) { connectOptions.args = [`--proxy-server=${proxyServer}`] } const { browser } = await connect(connectOptions) const pages = await browser.pages() const page = pages[0] await page.setRequestInterception(true) page.on('request', (req) => { const type = req.resourceType() if (["image", "stylesheet", "font", "media"].includes(type)) { req.abort() } else { req.continue() } }) return { browser, page } } const turnstile = require('./endpoints/turnstile') const cloudflare = require('./endpoints/cloudflare') const cloudflareCookies = require('./endpoints/cloudflare-cookies') app.post('/cloudflare-cookies', async (req, res) => { const data = req.body; if (!data || !data.domain) { return res.status(400).json({ message: "Parameter 'domain' diperlukan", status: "failed" }); } if (authToken && data.authToken !== authToken) { return res.status(401).json({ message: "Unauthorized", status: "failed" }); } if (global.browserLimit <= 0) { return res.status(429).json({ message: "Too Many Requests", status: "failed" }); } const cacheKey = JSON.stringify(data); const cached = readCache(cacheKey); if (cached) { return res.status(200).json({ ...cached, cached: true, status: "success" }); } global.browserLimit--; let result; let browser, page; try { const proxyServer = data.proxy ? `${data.proxy.hostname}:${data.proxy.port}` : null; const ctx = await createBrowser(proxyServer); browser = ctx.browser; page = ctx.page; if (data.mobile) { await page.setUserAgent('Mozilla/5.0 (Linux; Android 14; CPH2641 Build/UP1A.231005.007) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.97 Mobile Safari/537.36'); await page.setViewport({ width: 980, height: 1743 }); } result = await cloudflareCookies({ domain: data.domain, cookies: data.cookies || [], proxy: data.proxy, mobile: data.mobile || false }, page) .then(r => ({ ...r, status: "success" })) .catch(err => ({ code: 500, message: err.message, status: "failed" })); if (result.status === "success") { writeCache(cacheKey, result); } } catch (err) { result = { code: 500, message: err.message, status: "failed" }; } finally { if (browser) { try { await browser.close() } catch {} } global.browserLimit++; } res.status(result.code ?? 200).json(result); }); app.post('/cloudflare', async (req, res) => { const data = req.body if (!data || !data.mode) { return res.status(400).json({ message: "Parameter 'mode' diperlukan", status: "failed" }) } if (!data.siteKey || !data.domain) { return res.status(400).json({ message: "Parameter 'siteKey' dan 'domain' diperlukan", status: "failed" }) } if (authToken && data.authToken !== authToken) { return res.status(401).json({ message: "Unauthorized", status: "failed" }) } if (global.browserLimit <= 0) { return res.status(429).json({ message: "Too Many Requests", status: "failed" }) } let cacheKey, cached; if (data.mode === "iuam") { cacheKey = JSON.stringify(data); cached = readCache(cacheKey); if (cached) { return res.status(200).json({ ...cached, cached: true, status: "success" }); } } global.browserLimit--; let result; let browser, page; try { const proxyServer = data.proxy ? `${data.proxy.hostname}:${data.proxy.port}` : null; const ctx = await createBrowser(proxyServer); browser = ctx.browser; page = ctx.page; await page.goto('about:blank'); switch (data.mode) { case "turnstile": result = await turnstile(data, page) .then(token => ({ token, status: "success" })) .catch(err => ({ code: 500, message: err.message, status: "failed" })); break; case "iuam": result = await cloudflare(data, page) .then(r => ({ ...r, status: "success" })) .catch(err => ({ code: 500, message: err.message, status: "failed" })); if (!result.code || result.code === 200) { writeCache(cacheKey, result); } break; default: result = { code: 400, message: 'Invalid mode', status: "failed" }; } } catch (err) { result = { code: 500, message: err.message, status: "failed" }; } finally { if (browser) { try { await browser.close() } catch {} } global.browserLimit++; } res.status(result.code ?? 200).json(result); }); app.post('/turnstile', async (req, res) => { const data = req.body; if (!data || !data.siteKey || !data.domain) { return res.status(400).json({ message: "Parameter 'siteKey' dan 'domain' diperlukan", status: "failed" }); } if (authToken && data.authToken !== authToken) { return res.status(401).json({ message: "Unauthorized", status: "failed" }); } global.browserLimit--; let result; let browser, page; try { const proxyServer = data.proxy ? `${data.proxy.hostname}:${data.proxy.port}` : null; const ctx = await createBrowser(proxyServer); browser = ctx.browser; page = ctx.page; result = await turnstile(data, page) .then(token => ({ token, status: "success" })) .catch(err => ({ code: 500, message: err.message, status: "failed" })); } catch (err) { result = { code: 500, message: err.message, status: "failed" }; } finally { if (browser) { try { await browser.close() } catch {} } global.browserLimit++; } res.status(result.code ?? 200).json(result); }); app.use((req, res) => { res.status(404).json({ message: "Not Found", status: "failed" }); }); if (process.env.NODE_ENV !== 'development') { let server = app.listen(port, () => { console.log(`Server running on port ${port}`); console.log(`Domain: ${DOMAIN}`); }); try { server.timeout = global.timeOut; } catch {} } if (process.env.NODE_ENV === 'development') { module.exports = app; }