captcha / index.js
fourmovie's picture
update
5f99bb7
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;
}