| 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; | |
| } |