Fourstore commited on
Commit
4c05ad7
·
1 Parent(s): 3a0d6ef
Dockerfile ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:20-slim
2
+
3
+ RUN apt update && apt install -y \
4
+ wget gnupg ca-certificates xvfb \
5
+ fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 \
6
+ libatk1.0-0 libxss1 libnss3 libxcomposite1 libxdamage1 libxrandr2 libgbm1 \
7
+ && wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \
8
+ && apt install -y ./google-chrome-stable_current_amd64.deb \
9
+ && rm google-chrome-stable_current_amd64.deb
10
+
11
+ WORKDIR /app
12
+
13
+ RUN mkdir -p /app/endpoints && \
14
+ mkdir -p /app/cache
15
+
16
+ COPY package*.json ./
17
+ RUN npm install
18
+
19
+ COPY . .
20
+
21
+ EXPOSE 7860
22
+
23
+ CMD rm -f /tmp/.X99-lock && \
24
+ Xvfb :99 -screen 0 1024x768x24 & \
25
+ export DISPLAY=:99 && \
26
+ npm start
README.md CHANGED
@@ -3,9 +3,8 @@ title: Cf
3
  emoji: 💻
4
  colorFrom: pink
5
  colorTo: purple
6
- sdk: gradio
7
  sdk_version: 6.13.0
8
- app_file: app.py
9
  pinned: false
10
  license: apache-2.0
11
  short_description: 'bypass cloud turnstile '
 
3
  emoji: 💻
4
  colorFrom: pink
5
  colorTo: purple
6
+ sdk: docker
7
  sdk_version: 6.13.0
 
8
  pinned: false
9
  license: apache-2.0
10
  short_description: 'bypass cloud turnstile '
api_test.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import httpx
3
+
4
+ async def main():
5
+ async with httpx.AsyncClient(timeout=30.0) as client:
6
+ resp2 = await client.post(
7
+ "http://localhost:8080/cloudflare",
8
+ json={
9
+ "domain": "https://lksfy.com/",
10
+ "siteKey": "0x4AAAAAAA49NnPZwQijgRoi",
11
+ "mode": "turnstile",
12
+ },
13
+ )
14
+ print(resp2.json())
15
+
16
+ if __name__ == "__main__":
17
+ asyncio.run(main())
cache/cache.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "{\"domain\":\"https://v2links.org\",\"mode\":\"iuam\"}": {
3
+ "timestamp": 1758616160392,
4
+ "value": {
5
+ "cf_clearance": "qqs5f4MpFMgA0v78Qmh_HYDWoKhbwqlQ57bTW5KeIr8-1758616161-1.2.1.1-D5PdpmheHl.26ssIRKQBsXzPtPPkSXntEZ_H9FUJVt7MMTS_BEE8iH.E48MDzKtFBLwZqRYxE_1GLo1gj3ChXrwatOGEJcmGRUwavy2qvGgUPizn7qufd.sW0ULfhaRO7Gz_H_eO1TU3iEqCzltEUDNk0SviKRFkF8ozbvJ91MW_qmO.qrjQorbu_jxcgJv5BHs6rTNOitWtVDAmYMDukASq0viHXIUAIvTM.LIfQ88",
6
+ "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
7
+ "elapsed_time": 5.028
8
+ }
9
+ }
10
+ }
endpoints/cloudflare.js ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ async function cloudflare(data, page) {
2
+ return new Promise(async (resolve, reject) => {
3
+ if (!data.domain) return reject(new Error("Missing domain parameter"))
4
+
5
+ const startTime = Date.now()
6
+ let isResolved = false
7
+ let userAgent = null
8
+
9
+ const cl = setTimeout(() => {
10
+ if (!isResolved) {
11
+ isResolved = true
12
+ const elapsedTime = (Date.now() - startTime) / 1000
13
+ resolve({
14
+ cf_clearance: null,
15
+ user_agent: userAgent,
16
+ elapsed_time: elapsedTime,
17
+ })
18
+ }
19
+ }, 20000)
20
+
21
+ try {
22
+ if (data.proxy?.username && data.proxy?.password) {
23
+ await page.authenticate({
24
+ username: data.proxy.username,
25
+ password: data.proxy.password,
26
+ })
27
+ }
28
+
29
+ page.removeAllListeners("request")
30
+ page.removeAllListeners("response")
31
+ await page.setRequestInterception(true)
32
+
33
+ page.on("request", async (req) => {
34
+ try {
35
+ await req.continue()
36
+ } catch (_) {}
37
+ })
38
+
39
+ page.on("response", async (res) => {
40
+ try {
41
+ const url = res.url()
42
+ if (url.includes("/cdn-cgi/challenge-platform/")) {
43
+ const headers = res.headers()
44
+ if (headers["set-cookie"]) {
45
+ const match = headers["set-cookie"].match(/cf_clearance=([^;]+)/)
46
+ if (match) {
47
+ const cf_clearance = match[1]
48
+ const userAgent = (await res.request().headers())["user-agent"]
49
+ const elapsedTime = (Date.now() - startTime) / 1000
50
+
51
+ if (!isResolved) {
52
+ isResolved = true
53
+ clearTimeout(cl)
54
+
55
+ resolve({
56
+ cf_clearance,
57
+ user_agent: userAgent,
58
+ elapsed_time: elapsedTime,
59
+ })
60
+ }
61
+ }
62
+ }
63
+ }
64
+ } catch (_) {}
65
+ })
66
+
67
+ await page.goto(data.domain, { waitUntil: "domcontentloaded" })
68
+ userAgent = await page.evaluate(() => navigator.userAgent)
69
+ } catch (err) {
70
+ if (!isResolved) {
71
+ isResolved = true
72
+ clearTimeout(cl)
73
+ reject(err)
74
+ }
75
+ }
76
+ })
77
+ }
78
+
79
+ module.exports = cloudflare
endpoints/recaptchav2.js ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ async function recaptchaV2({ domain, proxy, siteKey, action = "submit", isInvisible = false }, page) {
2
+ if (!domain) throw new Error("Missing domain parameter");
3
+ if (!siteKey) throw new Error("Missing siteKey parameter");
4
+
5
+ const timeout = global.timeOut || 60000;
6
+ let isResolved = false;
7
+
8
+ const cl = setTimeout(async () => {
9
+ if (!isResolved) {
10
+ throw new Error("Timeout Error");
11
+ }
12
+ }, timeout);
13
+
14
+ try {
15
+ if (proxy?.username && proxy?.password) {
16
+ await page.authenticate({
17
+ username: proxy.username,
18
+ password: proxy.password,
19
+ });
20
+ }
21
+
22
+ const htmlContent = `
23
+ <!DOCTYPE html>
24
+ <html lang="en">
25
+ <head>
26
+ <meta charset="UTF-8">
27
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
28
+ <title>reCAPTCHA v2 Solver</title>
29
+ <style>
30
+ body {
31
+ font-family: Arial, sans-serif;
32
+ margin: 0;
33
+ padding: 20px;
34
+ background: #f5f5f5;
35
+ display: flex;
36
+ justify-content: center;
37
+ align-items: center;
38
+ min-height: 100vh;
39
+ }
40
+ .container {
41
+ background: white;
42
+ padding: 30px;
43
+ border-radius: 10px;
44
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
45
+ text-align: center;
46
+ }
47
+ .status {
48
+ margin-top: 20px;
49
+ padding: 10px;
50
+ border-radius: 5px;
51
+ background: #f8f9fa;
52
+ }
53
+ button {
54
+ background: #007bff;
55
+ color: white;
56
+ border: none;
57
+ padding: 10px 20px;
58
+ border-radius: 5px;
59
+ cursor: pointer;
60
+ margin: 10px;
61
+ }
62
+ button:hover {
63
+ background: #0056b3;
64
+ }
65
+ </style>
66
+ </head>
67
+ <body>
68
+ <div class="container">
69
+ <h2>reCAPTCHA v2 Solver</h2>
70
+ <p>SiteKey: ${siteKey}</p>
71
+ <div id="recaptcha-container">
72
+ <div class="g-recaptcha"
73
+ data-sitekey="${siteKey}"
74
+ data-callback="recaptchaCallback"
75
+ data-expired-callback="recaptchaExpired"
76
+ data-error-callback="recaptchaError"
77
+ data-size="${isInvisible ? 'invisible' : 'normal'}"
78
+ data-theme="light">
79
+ </div>
80
+ </div>
81
+ ${isInvisible ? '<button onclick="executeInvisible()">Execute reCAPTCHA</button>' : ''}
82
+ <button onclick="checkToken()">Check Token</button>
83
+ <div class="status" id="status">Waiting for reCAPTCHA...</div>
84
+ </div>
85
+
86
+ <script>
87
+ // Global variables
88
+ window.recaptchaToken = null;
89
+ window.recaptchaSolved = false;
90
+
91
+ // Callback functions
92
+ window.recaptchaCallback = function(token) {
93
+ console.log('reCAPTCHA token received:', token);
94
+ window.recaptchaToken = token;
95
+ window.recaptchaSolved = true;
96
+
97
+ document.getElementById('status').innerHTML = '✅ reCAPTCHA Solved! Token: ' + token.substring(0, 20) + '...';
98
+ document.getElementById('status').style.background = '#d4edda';
99
+ document.getElementById('status').style.color = '#155724';
100
+
101
+ // Store token in multiple ways
102
+ var input = document.createElement('input');
103
+ input.type = 'hidden';
104
+ input.name = 'g-recaptcha-response';
105
+ input.value = token;
106
+ input.id = 'recaptcha-token-input';
107
+ document.body.appendChild(input);
108
+
109
+ localStorage.setItem('recaptcha_token', token);
110
+ };
111
+
112
+ window.recaptchaExpired = function() {
113
+ console.log('reCAPTCHA expired');
114
+ window.recaptchaToken = null;
115
+ window.recaptchaSolved = false;
116
+ document.getElementById('status').innerHTML = '❌ reCAPTCHA Expired - Refreshing...';
117
+ document.getElementById('status').style.background = '#fff3cd';
118
+ document.getElementById('status').style.color = '#856404';
119
+
120
+ var existing = document.getElementById('recaptcha-token-input');
121
+ if (existing) existing.remove();
122
+
123
+ // Auto-refresh after expiration
124
+ setTimeout(() => {
125
+ if (window.grecaptcha) {
126
+ grecaptcha.reset();
127
+ }
128
+ }, 1000);
129
+ };
130
+
131
+ window.recaptchaError = function() {
132
+ console.log('reCAPTCHA error');
133
+ document.getElementById('status').innerHTML = '❌ reCAPTCHA Error';
134
+ document.getElementById('status').style.background = '#f8d7da';
135
+ document.getElementById('status').style.color = '#721c24';
136
+ };
137
+
138
+ window.executeInvisible = function() {
139
+ if (window.grecaptcha) {
140
+ grecaptcha.execute();
141
+ }
142
+ };
143
+
144
+ window.checkToken = function() {
145
+ const token = window.recaptchaToken || document.getElementById('recaptcha-token-input')?.value;
146
+ if (token) {
147
+ document.getElementById('status').innerHTML = 'Token: ' + token;
148
+ } else {
149
+ document.getElementById('status').innerHTML = 'No token yet';
150
+ }
151
+ };
152
+
153
+ // Auto-execute for invisible reCAPTCHA
154
+ window.onload = function() {
155
+ setTimeout(function() {
156
+ // For invisible reCAPTCHA, auto-execute
157
+ if (${isInvisible} && window.grecaptcha) {
158
+ grecaptcha.execute();
159
+ }
160
+
161
+ // For visible reCAPTCHA, try to find and click
162
+ if (!${isInvisible}) {
163
+ var iframe = document.querySelector('iframe[src*="recaptcha"]');
164
+ if (iframe) {
165
+ console.log('Attempting to interact with reCAPTCHA');
166
+ var rect = iframe.getBoundingClientRect();
167
+ var clickEvent = new MouseEvent('click', {
168
+ view: window,
169
+ bubbles: true,
170
+ cancelable: true,
171
+ clientX: rect.left + rect.width / 2,
172
+ clientY: rect.top + rect.height / 2
173
+ });
174
+ iframe.dispatchEvent(clickEvent);
175
+ }
176
+ }
177
+ }, 2000);
178
+ };
179
+ </script>
180
+
181
+ <!-- Load reCAPTCHA API -->
182
+ <script src="https://www.google.com/recaptcha/api.js" async defer></script>
183
+ </body>
184
+ </html>
185
+ `;
186
+
187
+ // Setup request interception
188
+ await page.setRequestInterception(true);
189
+ page.removeAllListeners("request");
190
+
191
+ page.on("request", async (request) => {
192
+ const url = request.url();
193
+
194
+ // Handle main document request
195
+ if ([domain, domain + "/"].includes(url) && request.resourceType() === "document") {
196
+ await request.respond({
197
+ status: 200,
198
+ contentType: "text/html",
199
+ body: htmlContent,
200
+ });
201
+ }
202
+ // Block unnecessary resources untuk mempercepat
203
+ else if (request.resourceType() === 'image' ||
204
+ request.resourceType() === 'stylesheet' ||
205
+ request.resourceType() === 'font') {
206
+ await request.abort();
207
+ }
208
+ else {
209
+ await request.continue();
210
+ }
211
+ });
212
+
213
+ // Navigate ke page
214
+ await page.goto(domain, {
215
+ waitUntil: "domcontentloaded",
216
+ timeout: timeout
217
+ });
218
+
219
+ // Tunggu reCAPTCHA container load
220
+ await page.waitForSelector('.g-recaptcha', { timeout: 10000 });
221
+
222
+ // Tunggu token tersedia dengan multiple strategies
223
+ const token = await page.waitForFunction(() => {
224
+ // Cek dari hidden input
225
+ const input = document.querySelector('#recaptcha-token-input');
226
+ if (input && input.value && input.value.length > 10) {
227
+ return input.value;
228
+ }
229
+
230
+ // Cek dari localStorage
231
+ const stored = localStorage.getItem('recaptcha_token');
232
+ if (stored && stored.length > 10) {
233
+ return stored;
234
+ }
235
+
236
+ // Cek dari global variable
237
+ if (window.recaptchaToken && window.recaptchaToken.length > 10) {
238
+ return window.recaptchaToken;
239
+ }
240
+
241
+ return null;
242
+ }, { timeout, polling: 100 });
243
+
244
+ const tokenValue = await token.jsonValue();
245
+
246
+ isResolved = true;
247
+ clearTimeout(cl);
248
+
249
+ if (!tokenValue || tokenValue.length < 10) {
250
+ throw new Error("Failed to get valid reCAPTCHA token");
251
+ }
252
+
253
+ console.log('Successfully obtained reCAPTCHA token');
254
+ return { token: tokenValue, type: 'recaptcha_v2' };
255
+
256
+ } catch (error) {
257
+ clearTimeout(cl);
258
+
259
+ // Fallback: coba ambil token dengan method lain
260
+ try {
261
+ const fallbackToken = await page.evaluate(() => {
262
+ const input = document.querySelector('#recaptcha-token-input');
263
+ return input ? input.value : null;
264
+ });
265
+
266
+ if (fallbackToken && fallbackToken.length > 10) {
267
+ return { token: fallbackToken, type: 'recaptcha_v2' };
268
+ }
269
+ } catch (e) {
270
+ // Ignore fallback error
271
+ }
272
+
273
+ throw new Error(`reCAPTCHA solving failed: ${error.message}`);
274
+ }
275
+ }
276
+
277
+ module.exports = recaptchaV2;
endpoints/turnstile.js ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ async function turnstile({ domain, proxy, siteKey }, page) {
2
+ if (!domain) throw new Error("Missing domain parameter");
3
+ if (!siteKey) throw new Error("Missing siteKey parameter");
4
+
5
+ const timeout = global.timeOut || 60000;
6
+ let isResolved = false;
7
+
8
+ const cl = setTimeout(async () => {
9
+ if (!isResolved) {
10
+ throw new Error("Timeout Error");
11
+ }
12
+ }, timeout);
13
+
14
+ try {
15
+ if (proxy?.username && proxy?.password) {
16
+ await page.authenticate({
17
+ username: proxy.username,
18
+ password: proxy.password,
19
+ });
20
+ }
21
+
22
+ const htmlContent = `
23
+ <!DOCTYPE html>
24
+ <html lang="en">
25
+ <body>
26
+ <div class="turnstile"></div>
27
+ <script src="https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onloadTurnstileCallback" defer></script>
28
+ <script>
29
+ window.onloadTurnstileCallback = function () {
30
+ turnstile.render('.turnstile', {
31
+ sitekey: '${siteKey}',
32
+ callback: function (token) {
33
+ var c = document.createElement('input');
34
+ c.type = 'hidden';
35
+ c.name = 'cf-response';
36
+ c.value = token;
37
+ document.body.appendChild(c);
38
+ },
39
+ });
40
+ };
41
+ </script>
42
+ </body>
43
+ </html>
44
+ `;
45
+
46
+ await page.setRequestInterception(true);
47
+ page.removeAllListeners("request");
48
+ page.on("request", async (request) => {
49
+ if ([domain, domain + "/"].includes(request.url()) && request.resourceType() === "document") {
50
+ await request.respond({
51
+ status: 200,
52
+ contentType: "text/html",
53
+ body: htmlContent,
54
+ });
55
+ } else {
56
+ await request.continue();
57
+ }
58
+ });
59
+
60
+ await page.goto(domain, { waitUntil: "domcontentloaded" });
61
+
62
+ await page.waitForSelector('[name="cf-response"]', { timeout });
63
+
64
+ const token = await page.evaluate(() => {
65
+ try {
66
+ return document.querySelector('[name="cf-response"]').value;
67
+ } catch {
68
+ return null;
69
+ }
70
+ });
71
+
72
+ isResolved = true;
73
+ clearTimeout(cl);
74
+
75
+ if (!token || token.length < 10) throw new Error("Failed to get token");
76
+ return token;
77
+
78
+ } catch (e) {
79
+ clearTimeout(cl);
80
+ throw e;
81
+ }
82
+ }
83
+
84
+ module.exports = turnstile;
index.js ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const express = require('express');
2
+ const { connect } = require("puppeteer-real-browser");
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const app = express();
7
+ const port = process.env.PORT || 7860;
8
+ const authToken = process.env.authToken || null; // Set null biar gak perlu auth
9
+ const domain = process.env.DOMAIN || `https://fourstore-cf.hf.space`;
10
+
11
+ global.browserLimit = Number(process.env.browserLimit) || 20;
12
+ global.timeOut = Number(process.env.timeOut) || 60000;
13
+
14
+ const CACHE_DIR = path.join(__dirname, "cache");
15
+ const CACHE_FILE = path.join(CACHE_DIR, "cache.json");
16
+ const CACHE_TTL = 5 * 60 * 1000;
17
+
18
+ function loadCache() {
19
+ if (!fs.existsSync(CACHE_FILE)) return {};
20
+ try {
21
+ return JSON.parse(fs.readFileSync(CACHE_FILE, 'utf-8'));
22
+ } catch {
23
+ return {};
24
+ }
25
+ }
26
+
27
+ function saveCache(cache) {
28
+ if (!fs.existsSync(CACHE_DIR)) {
29
+ fs.mkdirSync(CACHE_DIR, { recursive: true });
30
+ }
31
+ fs.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2), 'utf-8');
32
+ }
33
+
34
+ function readCache(key) {
35
+ const cache = loadCache();
36
+ const entry = cache[key];
37
+ if (entry && Date.now() - entry.timestamp < CACHE_TTL) {
38
+ return entry.value;
39
+ }
40
+ return null;
41
+ }
42
+
43
+ function writeCache(key, value) {
44
+ const cache = loadCache();
45
+ cache[key] = { timestamp: Date.now(), value };
46
+ saveCache(cache);
47
+ }
48
+
49
+ app.use(express.json());
50
+ app.use(express.urlencoded({ extended: true }));
51
+
52
+ // ROUTE UTAMA APP.GET("/")
53
+ app.get("/", (req, res) => {
54
+ res.json({
55
+ message: "Server is running!",
56
+ domain: domain,
57
+ endpoints: {
58
+ cloudflare: `${domain}/cloudflare`,
59
+ turnstile: `${domain}/cloudflare`,
60
+ recaptcha: `${domain}/cloudflare`
61
+ },
62
+ status: {
63
+ browserLimit: global.browserLimit,
64
+ timeOut: global.timeOut,
65
+ authRequired: authToken !== null
66
+ }
67
+ });
68
+ });
69
+
70
+ if (process.env.NODE_ENV !== 'development') {
71
+ let server = app.listen(port, () => {
72
+ console.log(`Server running on port ${port}`);
73
+ console.log(`Domain: ${domain}`);
74
+ console.log(`Auth required: ${authToken !== null}`);
75
+ });
76
+ try {
77
+ server.timeout = global.timeOut;
78
+ } catch {}
79
+ }
80
+
81
+ async function createBrowser(proxyServer = null) {
82
+ const connectOptions = {
83
+ headless: false,
84
+ turnstile: true,
85
+ connectOption: { defaultViewport: null },
86
+ disableXvfb: false,
87
+ };
88
+ if (proxyServer) connectOptions.args = [`--proxy-server=${proxyServer}`];
89
+
90
+ const { browser } = await connect(connectOptions);
91
+ const [page] = await browser.pages();
92
+
93
+ await page.goto('about:blank');
94
+ await page.setRequestInterception(true);
95
+ page.on('request', (req) => {
96
+ const type = req.resourceType();
97
+ if (["image", "stylesheet", "font", "media"].includes(type)) req.abort();
98
+ else req.continue();
99
+ });
100
+
101
+ return { browser, page };
102
+ }
103
+
104
+ const turnstile = require('./endpoints/turnstile');
105
+ const cloudflare = require('./endpoints/cloudflare');
106
+ const recaptchaV2 = require('./endpoints/recaptchav2');
107
+
108
+ app.post('/cloudflare', async (req, res) => {
109
+ const data = req.body;
110
+ if (!data || typeof data.mode !== 'string')
111
+ return res.status(400).json({ message: 'Bad Request: missing or invalid mode' });
112
+
113
+ // COMMENT/HAPUS pengecekan auth token biar gak perlu auth
114
+ // if (authToken && data.authToken !== authToken)
115
+ // return res.status(401).json({ message: 'Unauthorized' });
116
+
117
+ if (global.browserLimit <= 0)
118
+ return res.status(429).json({ message: 'Too Many Requests' });
119
+
120
+ let cacheKey, cached;
121
+ if (data.mode === "iuam" || data.mode === "recaptcha") {
122
+ cacheKey = JSON.stringify(data);
123
+ cached = readCache(cacheKey);
124
+ if (cached) return res.status(200).json({ ...cached, cached: true });
125
+ }
126
+
127
+ global.browserLimit--;
128
+ let result, browser;
129
+
130
+ try {
131
+ const proxyServer = data.proxy ? `${data.proxy.hostname}:${data.proxy.port}` : null;
132
+ const ctx = await createBrowser(proxyServer);
133
+ browser = ctx.browser;
134
+ const page = ctx.page;
135
+
136
+ await page.goto('about:blank');
137
+
138
+ switch (data.mode) {
139
+ case "turnstile":
140
+ result = await turnstile(data, page)
141
+ .then(token => ({ token }))
142
+ .catch(err => ({ code: 500, message: err.message }));
143
+ break;
144
+
145
+ case "iuam":
146
+ result = await cloudflare(data, page)
147
+ .then(r => ({ ...r }))
148
+ .catch(err => ({ code: 500, message: err.message }));
149
+ if (!result.code || result.code === 200) writeCache(cacheKey, result);
150
+ break;
151
+
152
+ case "recaptcha":
153
+ result = await recaptchaV2(data, page)
154
+ .then(r => ({ ...r }))
155
+ .catch(err => ({ code: 500, message: err.message }));
156
+ if (!result.code || result.code === 200) writeCache(cacheKey, result);
157
+ break;
158
+
159
+ default:
160
+ result = { code: 400, message: 'Invalid mode' };
161
+ }
162
+ } catch (err) {
163
+ result = { code: 500, message: err.message };
164
+ } finally {
165
+ if (browser) try { await browser.close(); } catch {}
166
+ global.browserLimit++;
167
+ }
168
+
169
+ res.status(result.code ?? 200).json(result);
170
+ });
171
+
172
+ app.use((req, res) => {
173
+ res.status(404).json({ message: 'Not Found' });
174
+ });
175
+
176
+ if (process.env.NODE_ENV === 'development') {
177
+ module.exports = app;
178
+ }
package.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "cf-bypass",
3
+ "version": "1.0",
4
+ "description": "get the cf_clearance cookie from any website",
5
+ "scripts": {
6
+ "start": "node index.js",
7
+ "dev": "nodemon index.js"
8
+ },
9
+ "dependencies": {
10
+ "express": "^5.1.0",
11
+ "puppeteer-real-browser": "^1.4.0"
12
+ },
13
+ "devDependencies": {
14
+ "nodemon": "^3.1.10"
15
+ }
16
+ }