From 772ed5a1761150d2e7da5d69efbbd78400c2bb9a Mon Sep 17 00:00:00 2001 From: estebanthilliez Date: Fri, 24 Apr 2026 22:21:24 +0200 Subject: [PATCH] add cookie wait endpoint --- README.md | 44 ++++++++++++++++++++++++++++++++ api_test.py | 27 +++++++++++++------- endpoints/cookie.js | 62 +++++++++++++++++++++++++++++++++++++++++++++ index.js | 47 ++++++++++++++++++++++++++++++++++ 4 files changed, 171 insertions(+), 9 deletions(-) create mode 100644 endpoints/cookie.js diff --git a/README.md b/README.md index fb3314a..04981d0 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ A Node.js service that automates Chromium to bypass **Cloudflare IUAM** and **Tu - **Cloudflare IUAM Bypass**: Automatically solves "I'm Under Attack Mode" challenges super fast within 3.337 seconds 💖 - **Turnstile Challenge Solver**: Handles Cloudflare Turnstile captchas +- **Generic Cookie Waiter**: Opens a page, waits for a named cookie, and returns it - **Proxy Support**: Full HTTP proxy integration with authentication - **Smart Timeout**: 20-second timeout with graceful null responses - **Browser Management**: Concurrent browser limit control @@ -110,6 +111,48 @@ Bypass Cloudflare protection and get cookies/tokens. } ``` +### POST /cookie + +Open a page and wait for a specific cookie to appear. + +#### Request Body +```json +{ + "domain": "https://example.com/", + "cookieName": "session_id" +} +``` + +#### Parameters +- **`domain`** (required): Target website URL +- **`cookieName`** (required): Cookie name to wait for +- **`user_agent`** (optional): User-Agent to use for the browser session +- **`proxy`** (optional): Proxy configuration object + +#### Response (Success) +```json +{ + "cookie_name": "session_id", + "cookie_value": "abc123", + "cookie_domain": ".example.com", + "cookie_path": "/", + "http_only": true, + "secure": true, + "user_agent": "Mozilla/5.0...", + "elapsed_time": 1.42 +} +``` + +#### Response (No Cookie Found) +```json +{ + "cookie_name": "session_id", + "cookie_value": null, + "user_agent": "Mozilla/5.0...", + "elapsed_time": 60.0 +} +``` + ## 🌐 Proxy Configuration The service supports HTTP proxies with authentication: @@ -141,6 +184,7 @@ python api_test.py cf-bypass/ ├── endpoints/ │ ├── cloudflare.js # IUAM bypass logic +│ ├── cookie.js # Generic cookie waiter │ └── turnstile.js # Turnstile solver ├── cache/ │ └── cache.json # Response cache diff --git a/api_test.py b/api_test.py index 4419bcd..9a4d089 100644 --- a/api_test.py +++ b/api_test.py @@ -12,15 +12,24 @@ async def main(): ) print(resp1.json()) - resp2 = await client.post( - "http://localhost:8080/cloudflare", - json={ - "domain": "https://lksfy.com/", - "siteKey": "0x4AAAAAAA49NnPZwQijgRoi", - "mode": "turnstile", - }, - ) - print(resp2.json()) + resp2 = await client.post( + "http://localhost:8080/cloudflare", + json={ + "domain": "https://lksfy.com/", + "siteKey": "0x4AAAAAAA49NnPZwQijgRoi", + "mode": "turnstile", + }, + ) + print(resp2.json()) + + resp3 = await client.post( + "http://localhost:8080/cookie", + json={ + "domain": "https://example.com/", + "cookieName": "session_id", + }, + ) + print(resp3.json()) if __name__ == "__main__": asyncio.run(main()) diff --git a/endpoints/cookie.js b/endpoints/cookie.js new file mode 100644 index 0000000..7bb608d --- /dev/null +++ b/endpoints/cookie.js @@ -0,0 +1,62 @@ +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + +function logBrowserCookies({ domain, cookieName, cookies }) { + console.log( + `[cookie] Browser cookies before return for ${domain} (${cookieName}): ${JSON.stringify(cookies)}` + ) +} + +async function waitForCookie({ domain, proxy, cookieName }, page) { + if (!domain) throw new Error("Missing domain parameter") + if (!cookieName) throw new Error("Missing cookieName parameter") + + const timeout = global.timeOut || 60000 + const pollInterval = 250 + const startTime = Date.now() + + if (proxy?.username && proxy?.password) { + await page.authenticate({ + username: proxy.username, + password: proxy.password, + }) + } + + await page.goto(domain, { waitUntil: "domcontentloaded" }) + + const userAgent = await page.evaluate(() => navigator.userAgent) + + while (Date.now() - startTime < timeout) { + const cookies = await page.cookies() + const match = cookies.find((cookie) => cookie.name === cookieName) + + if (match) { + logBrowserCookies({ domain, cookieName, cookies }) + return { + cookie_name: match.name, + cookie_value: match.value, + cookie_domain: match.domain, + cookie_path: match.path, + http_only: match.httpOnly, + secure: match.secure, + user_agent: userAgent, + elapsed_time: (Date.now() - startTime) / 1000, + } + } + + await sleep(pollInterval) + } + + const cookies = await page.cookies() + logBrowserCookies({ domain, cookieName, cookies }) + + return { + cookie_name: cookieName, + cookie_value: null, + user_agent: userAgent, + elapsed_time: (Date.now() - startTime) / 1000, + } +} + +module.exports = waitForCookie diff --git a/index.js b/index.js index 176b798..c778154 100644 --- a/index.js +++ b/index.js @@ -91,6 +91,7 @@ async function createBrowser(proxyServer = null) { const turnstile = require('./endpoints/turnstile') const cloudflare = require('./endpoints/cloudflare') +const waitForCookie = require('./endpoints/cookie') app.post('/cloudflare', async (req, res) => { const data = req.body @@ -167,6 +168,52 @@ app.post('/cloudflare', async (req, res) => { res.status(result.code ?? 200).json(result) }) +app.post('/cookie', async (req, res) => { + const data = req.body + if (!data || typeof data.domain !== 'string' || typeof data.cookieName !== 'string') { + return res.status(400).json({ message: 'Bad Request: missing or invalid domain/cookieName' }) + } + if (data.user_agent && typeof data.user_agent !== 'string') { + return res.status(400).json({ message: 'Bad Request: invalid user_agent' }) + } + if (authToken && data.authToken !== authToken) { + return res.status(401).json({ message: 'Unauthorized' }) + } + + if (global.browserLimit <= 0) { + return res.status(429).json({ message: 'Too Many Requests' }) + } + + 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') + if (data.user_agent) { + await page.setUserAgent(data.user_agent) + } + + result = await waitForCookie(data, page) + .then((cookie) => ({ ...cookie })) + .catch((err) => ({ code: 500, message: err.message })) + } catch (err) { + result = { code: 500, message: err.message } + } 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' }) })