├── .gitattributes
├── README.md
├── Thumbs.db
├── example.js
├── html
├── CloudFreed.html
├── CloudFreed.png
├── IUAMChallenge.html
├── InvisibleChallenge.html
├── RecaptchaInvisibleChallenge.html
├── Thumbs.db
├── TurnstileChallenge.html
└── icons.html
├── index.js
├── lib
├── CheckDebuggingEndpoint.js
├── Click.js
├── CloudFreedHTML.js
├── ConvertToCDPHeaders.js
├── DeleteTempUserDataFolders.js
├── Extension
│ ├── background.js
│ ├── click.js
│ ├── manifest.json
│ ├── proxy.js
│ └── script.js
├── FindAvailablePort.js
├── GetDefaultChromePath.js
├── GetHomeDirectory.js
├── KillProcess.js
├── Proxy.js
├── Solve copy.js
├── Solve.js
├── SolveIUAM.js
├── SolveTurnstile.js
├── SolveV3.js
├── StatusText.js
├── ValidateURL.js
├── curl.js
├── curl
│ ├── curl-ca-bundle.crt
│ └── curl.exe
├── delay.js
├── fs.js
├── proxyManager
│ ├── background.js
│ ├── manifest.json
│ └── script.js
└── turnstilePatch
│ ├── manifest.json
│ └── script.js
├── package-lock.json
└── package.json
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.js linguist-language=JavaScript
2 | *.html linguist-language=JavaScript
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## STATUS: Active
2 |
3 | Updates are on the way!
4 | V4 Just released, please report any errors in Issues.
5 |
6 | ## Discord Server
7 | [](https://discord.gg/5ncqYYQTPN)
8 |
9 | ## Notice
10 | If you like the repo, please consider starring it, starring repos will help it spread.
11 | CloudFreed is 100% Free, CloudFreed can stop working at any time.
12 | Files may have problems loading correctly, this is because of the request interception. This may be fixed in the future!
13 |
14 | ## Introduction
15 |
16 |

17 |
CloudFreed V4
18 |
19 | [Join the CloudFreed Server](https://discord.gg/8F852cXVbX)
20 |
21 |
22 | CloudFreed is a powerful tool designed to bypass Cloudflare anti-bot protection, allowing users to access websites without being restricted by captchas or Cloudflare's security measures.
23 |
24 | ## Installation
25 | Before using CloudFreed, ensure that you have Node.js installed on your system. If not, you can download and install it from [Node.js website](https://nodejs.org/).
26 |
27 | Once Node.js is installed, follow these steps to set up CloudFreed:
28 |
29 | 1. Clone or download the CloudFreed repository to your local machine, you can get the latest download [here](https://github.com/Akmal-CloudFreed/CloudFreed-CloudFlare-bypass/archive/refs/heads/main.zip).
30 | 2. Extract the file.
31 | 3. Open a terminal and navigate to the directory where you have cloned/downloaded CloudFreed.
32 | 4. Run the following command to install dependencies:
33 |
34 | ```
35 | npm i
36 | ```
37 | alternatively, you can use:
38 | ```
39 | npm install
40 | ```
41 | ## Usage
42 | After installing dependencies, you can start using CloudFreed. The main functionality is provided through the `CloudFreed` function, which returns the `cf_clearence` cookie necessary for bypassing Cloudflare protection.
43 |
44 | To use CloudFreed in your project, look at example.js
45 |
46 | ### Example:
47 | Find example in example.js
48 |
49 | ## Contribution
50 |
51 | Suggestions and pull requests are welcomed!.
52 |
53 | ## Support the project
54 |
55 | Supporting the project will most likely contribute to the creation of newer versions, and maybe even newer projects!
56 | Please consider donating if you like the project.
57 |
58 | [Support me at ko-fi.com](https://ko-fi.com/akmal2)
59 |
60 | ---
61 |
62 | ## Note
63 | CloudFreed is intended for educational and research purposes only. Please use it responsibly and respect the terms of service of the websites you visit.
64 |
--------------------------------------------------------------------------------
/Thumbs.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akmal-abar/CloudFreed-CloudFlare-solver-bypass/568fe1ef56ddad4b0249ac0e0112d5b4dbba0b07/Thumbs.db
--------------------------------------------------------------------------------
/example.js:
--------------------------------------------------------------------------------
1 | import CloudFreed from "./index.js"
2 | import delay from "./lib/delay.js"
3 |
4 | /*
5 | documentation for instance.Solve data.
6 |
7 | (property) Solve?: ((data: {
8 | url: string;
9 | type: string;
10 | sitekey: string | undefined;
11 | userAgent: string | undefined;
12 | action: string | undefined;
13 | proxy: {
14 | scheme: string;
15 | host: string;
16 | port: number;
17 | username: string | undefined;
18 | password: string | undefined;
19 | };
20 | }) => Promise<...>) | undefined
21 | */
22 |
23 | const CF = new CloudFreed()
24 |
25 | const instance = await CF.start(false, true)
26 |
27 | console.log(instance)
28 |
29 | console.log(await instance.Solve({
30 | type: "V3",
31 | url: "www.subber.xyz",
32 | //proxy: { scheme: "http", host: "152.26.229.42", port: 9443 },
33 | userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"
34 | }))
35 |
36 | await delay(3723498) // optional, stop (kinda) after testing V3.
37 |
38 | console.log(await instance.Solve({
39 | type: "Turnstile",
40 | url: "www.coronausa.com",
41 | sitekey: "0x4AAAAAAAH4-VmiV_O_wBN-",
42 | //proxy: { scheme: "http", host: "152.26.229.42", port: 9443 },
43 | userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
44 | }))
45 |
46 | console.log(await instance.Solve({
47 | type: "RecaptchaInvisible",
48 | url: "https://antcpt.com/score_detector/",
49 | sitekey: "6LcR_okUAAAAAPYrPe-HK_0RULO1aZM15ENyM-Mf",
50 | action: "homepage",
51 | //proxy: { scheme: "http", host: "152.26.229.42", port: 9443 },
52 | userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
53 | }))
54 |
55 | console.log(await instance.Solve({
56 | type: "Invisible",
57 | url: "discord.com",
58 | //proxy: { scheme: "http", host: "152.26.229.42", port: 9443 },
59 | userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
60 | }))
61 |
62 | console.log(await instance.Solve({
63 | type: "IUAM",
64 | url: "bloxmoon.com",
65 | //proxy: { scheme: "http", host: "152.26.229.42", port: 9443 },
66 | userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
67 | }))
68 |
69 | console.log(await instance.Solve({
70 | type: "V3",
71 | url: "www.subber.xyz",
72 | //proxy: { scheme: "http", host: "152.26.229.42", port: 9443 },
73 | userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
74 | }))
75 |
76 | await instance.Close()
--------------------------------------------------------------------------------
/html/CloudFreed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akmal-abar/CloudFreed-CloudFlare-solver-bypass/568fe1ef56ddad4b0249ac0e0112d5b4dbba0b07/html/CloudFreed.png
--------------------------------------------------------------------------------
/html/IUAMChallenge.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | CloudFreed
7 |
8 |
57 |
58 |
59 |
60 |
61 |

62 |
63 |
Solving Challenge
64 |
Please wait...
65 |
Developed by Akmal
66 |
67 | ![script]!
68 |
69 |
--------------------------------------------------------------------------------
/html/Thumbs.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akmal-abar/CloudFreed-CloudFlare-solver-bypass/568fe1ef56ddad4b0249ac0e0112d5b4dbba0b07/html/Thumbs.db
--------------------------------------------------------------------------------
/html/icons.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import ValidateURL from "./lib/ValidateURL.js";
2 | import GetDefaultChromePath from "./lib/GetDefaultChromePath.js";
3 | import GetHomeDirectory from "./lib/GetHomeDirectory.js";
4 | import delay from "./lib/delay.js";
5 | import DeleteTempUserDataFolders from "./lib/DeleteTempUserDataFolders.js";
6 | import FindAvailablePort from "./lib/FindAvailablePort.js";
7 | import CheckDebuggingEndpoint from "./lib/CheckDebuggingEndpoint.js";
8 | import KillProcess from "./lib/KillProcess.js";
9 | import Solve from "./lib/Solve.js";
10 |
11 | // Separate library imports from module imports
12 | import CDP from "chrome-remote-interface";
13 | import fs from "fs/promises";
14 | import { spawn } from "child_process";
15 | import path from 'path';
16 | import { fileURLToPath } from 'url';
17 |
18 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
19 | const EXTENSION_PATH = path.join(__dirname, "lib", "Extension");
20 | const chromium = GetDefaultChromePath();
21 | const homedir = GetHomeDirectory();
22 |
23 | class CloudFreed {
24 | /**
25 | * Starts a CloudFreed Instance
26 | * @param {boolean|undefined} headless - Whether the instance should run in headless mode.
27 | * @param {boolean|undefined} proxyOverride
28 | */
29 | async start(headless, proxyOverride) {
30 | let chromeProcess;
31 |
32 | try {
33 | // Check if OS is valid
34 | if (!chromium && !homedir) {
35 | return {
36 | success: false,
37 | code: 500,
38 | errormessage: "Unsupported OS, please use darwin, linux, or windows."
39 | };
40 | }
41 |
42 | // Check if Chrome is installed or uninstalled/misplaced
43 | try {
44 | await fs.access(chromium);
45 | } catch (error) {
46 | return {
47 | success: false,
48 | code: 500,
49 | errormessage: `Google Chrome is not installed on host server, please install Google Chrome and try again.\nAttempted path: ${chromium}`
50 | };
51 | }
52 |
53 | const cloudflareBypassDir = path.join(homedir, 'CloudFreed');
54 | await DeleteTempUserDataFolders(path.join(cloudflareBypassDir, 'DataDirs'));
55 |
56 | // Find an available port
57 | const port = await FindAvailablePort(10000, 60000);
58 | const random8DigitNumber = Math.floor(10000000 + Math.random() * 90000000);
59 | const dataDir = path.join(cloudflareBypassDir, 'DataDirs', `CloudFreed_${Date.now()+random8DigitNumber}`);
60 |
61 | // Configure Chrome arguments
62 | const chromeArgs = [
63 | `--user-data-dir=${dataDir}`,
64 | '--window-size=512,512',
65 | '--disable-dev-shm-usage',
66 | '--disable-software-rasterizer',
67 | '--mute-audio',
68 | '--disable-background-networking',
69 | '--disable-web-security',
70 | '--disk-cache-size=1',
71 | '--disable-default-apps',
72 | '--disable-translate',
73 | '--disk-cache-size=0',
74 | '--disable-application-cache',
75 | '--disable-gpu',
76 | '--disable-features=CookiesWithoutSameSiteMustBeSecure',
77 | `--disable-extensions-except=${EXTENSION_PATH}`,
78 | `--load-extension=${EXTENSION_PATH}`,
79 | '--no-first-run',
80 | '--disable-blink-features=AutomationControlled',
81 | '--no-sandbox',
82 | '--disable-setuid-sandbox',
83 | '--lang=en',
84 | '--disable-sync',
85 | `--remote-debugging-port=${port}`,
86 | '--window-name=CloudFreed',
87 | '--allow-file-access-from-files',
88 | '--ignore-certificate-errors',
89 | '--disable-infobars',
90 | //'--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"', // default user agent if the user inputs no UA, it get outputted in the response.
91 | `--app=file:///${path.join(__dirname, "html", "CloudFreed.html")}`,
92 | ];
93 |
94 | if (headless === true) {
95 | chromeArgs.push('--headless=new')
96 | }
97 |
98 | // Launch Chrome in headless mode
99 | chromeProcess = spawn(chromium, chromeArgs, {
100 | detached: true,
101 | stdio: 'ignore'
102 | });
103 |
104 | const PID = chromeProcess.pid;
105 | chromeProcess.unref();
106 |
107 | // Fetch Chrome version information
108 | const versionInfo = await CheckDebuggingEndpoint(port);
109 |
110 | if (!versionInfo) {
111 | await KillProcess(PID);
112 | return {
113 | success: false,
114 | code: 500,
115 | errormessage: "Error occurred on our side: VersionInfo could not be parsed from chrome. returned null."
116 | };
117 | }
118 |
119 | // If WebSocket debugger URL is available, establish WebSocket connection
120 | if (versionInfo.webSocketDebuggerUrl && versionInfo["User-Agent"]) {
121 | let solving = false
122 | const originalUserAgent = versionInfo["User-Agent"].includes("Headless") ? versionInfo["User-Agent"].replace("Headless", "") : versionInfo["User-Agent"]
123 | console.log("Process started with " + originalUserAgent + " user agent")
124 | const client = await CDP({ port });
125 | let target = null, extensionTarget = null, targetId, sessionId = null, extensionSessionId = null;
126 |
127 | for (let i = 0; i < 10; i++) { // Try up to 10 times
128 | const targets = (await client.Target.getTargets()).targetInfos;
129 | target = targets.find(t => t.type === "page" && t.title === "CloudFreed");
130 | extensionTarget = targets.find((t) => t.type === "service_worker" && !t.url.includes("neajdpp"));
131 |
132 | if (target && extensionTarget) {
133 | break; // Exit the loop if the target is found
134 | }
135 |
136 | await delay(500) // Wait for 500ms before retrying
137 | }
138 |
139 | if (target && extensionTarget && target.targetId && extensionTarget.targetId) {
140 | targetId = target.targetId;
141 | const extensionTargetId = extensionTarget.targetId
142 | extensionSessionId = (await client.Target.attachToTarget({ targetId: extensionTargetId, flatten: true })).sessionId;
143 | sessionId = (await client.Target.attachToTarget({ targetId, flatten: true })).sessionId;
144 | } else {
145 | return {
146 | success: false,
147 | code: 500,
148 | errormessage: "Error occurred while initializing."
149 | };
150 | }
151 |
152 | await client.Network.enable();
153 | await client.DOM.enable(sessionId)
154 | await client.Log.enable(sessionId)
155 | await client.Network.setCacheDisabled({ cacheDisabled: true })
156 | await client.Emulation.setFocusEmulationEnabled({ enabled: true }, sessionId)
157 |
158 | let solve = new Solve(client, sessionId, originalUserAgent, extensionSessionId, proxyOverride)
159 |
160 | return {
161 | success: true,
162 | code: 200,
163 | userAgent: originalUserAgent,
164 | webSocketDebuggerUrl: versionInfo.webSocketDebuggerUrl,
165 | port,
166 |
167 | /**
168 | * Solves CloudFlare Challenge.
169 | * @param {CDP.Client} client
170 | * @param {{url: string, type: string, sitekey: string|undefined, userAgent: string|undefined, action:string|undefined, proxy: {scheme: string, host: string, port: Number, username: string|undefined, password: string|undefined}}} data
171 | * @param {string} sessionId
172 | */
173 | Solve: async (data) => {
174 | try {
175 | if (solving === false) {
176 | if (typeof data === "object") {
177 | if (data.url && typeof data.url === "string") {
178 | if (data.type && typeof data.type === "string") {
179 | solving = true
180 | data.url = ValidateURL(data.url);
181 | console.log('Solving ' + data.url);
182 |
183 | const solveWithTimeout = new Promise(async (resolve, reject) => {
184 | try {
185 | const response = await solve.Solve(data);
186 |
187 | await client.Page.navigate({ url: `file:///${path.join(__dirname, "html", "CloudFreed.html")}` }, sessionId);
188 |
189 | solving = false
190 |
191 | resolve(response);
192 | } catch (error) {
193 | solving = false
194 |
195 | resolve({
196 | success: false,
197 | code: 500,
198 | errormessage: "Error occurred while initializing.",
199 | error
200 | });
201 | }
202 | });
203 |
204 | const timeout = new Promise((resolve) => {
205 | let elapsed = 0;
206 |
207 | const interval = setInterval(async () => {
208 | elapsed += 1;
209 |
210 | // Check if the solving flag is false or if we've reached 60 seconds (60 iterations)
211 | if (solving === false || elapsed >= 60) {
212 | clearInterval(interval); // Stop the interval after 60 seconds or if solving is false
213 |
214 | if (solving === true) {
215 | try {
216 | // Navigate the page if solving is still true after 60 seconds
217 | await client.Page.navigate({ url: `file:///${path.join(__dirname, "html", "CloudFreed.html")}` }, sessionId);
218 |
219 | solving = false;
220 |
221 | resolve({ success: false, code: 408, errormessage: "Request timed out after 60 seconds." });
222 | } catch (error) {
223 | resolve({ success: false, code: 408, errormessage: "Request timed out with an error after 60 seconds." });
224 | }
225 | } else {
226 | return; // Resolve immediately if solving became false before 60 seconds
227 | }
228 | }
229 | }, 1000); // Run every 1 second
230 | });
231 |
232 | // Use Promise.race to return whichever promise resolves first (response or timeout)
233 | const result = await Promise.race([solveWithTimeout, timeout]);
234 |
235 | solving = false
236 |
237 | return result;
238 | } else {
239 | return {
240 | success: false,
241 | code: 400,
242 | errormessage: `Invalid input: Expected data.type to be of type "string", but received "${typeof data.url}".`
243 | };
244 | }
245 | } else {
246 | return {
247 | success: false,
248 | code: 400,
249 | errormessage: `Invalid input: Expected data.url to be of type "string", but received "${typeof data.url}".`
250 | };
251 | }
252 | } else {
253 | return {
254 | success: false,
255 | code: 400,
256 | errormessage: `Invalid input: Expected data to be of type "Object", but received "${typeof data}".`
257 | };
258 | }
259 | } else {
260 | return {
261 | success: false,
262 | code: 503,
263 | errormessage: "Instance currently busy."
264 | };
265 | }
266 | } catch (error) {
267 | return {
268 | success: false,
269 | code: 500,
270 | errormessage: "Error occurred while initializing.",
271 | error
272 | };
273 | }
274 | },
275 |
276 | /**
277 | * Closes CloudFreed Instance.
278 | */
279 | Close: async () => {
280 | try {
281 | if (client) {
282 | client.close();
283 | }
284 |
285 | if (PID) {
286 | KillProcess(PID);
287 | }
288 |
289 | return {
290 | success: true,
291 | code: 200
292 | };
293 | } catch {
294 | return {
295 | success: false,
296 | code: 500,
297 | errormessage: "Error occurred while closing."
298 | };
299 | }
300 | }
301 | };
302 | }
303 | } catch (error) {
304 | if (chromeProcess) {
305 | KillProcess(chromeProcess.pid);
306 | chromeProcess.kill();
307 | }
308 |
309 | return {
310 | success: false,
311 | code: 500,
312 | error,
313 | errormessage: `Error occurred on our side: ${error.message}`
314 | };
315 | }
316 | }
317 | }
318 |
319 | export default CloudFreed;
320 |
--------------------------------------------------------------------------------
/lib/CheckDebuggingEndpoint.js:
--------------------------------------------------------------------------------
1 | import delay from "./delay.js";
2 |
3 | async function CheckDebuggingEndpoint(port, maxAttempts = 10, delaytime = 1000) {
4 | let attempts = 0;
5 | while (attempts < maxAttempts) {
6 | attempts++;
7 | const url = `http://127.0.0.1:${port}/json/version`;
8 | try {
9 | const response = await fetch(url);
10 | if (response.ok) {
11 | return await response.json();
12 | } else {
13 | throw new Error(`HTTP error ${response.status}: ${response.statusText}`);
14 | }
15 | } catch {}
16 | await delay(delaytime)
17 | }
18 | console.error(`Maximum attempts (${maxAttempts}) reached. Could not connect to Chrome.`);
19 | return null;
20 | }
21 |
22 | export default CheckDebuggingEndpoint
--------------------------------------------------------------------------------
/lib/Click.js:
--------------------------------------------------------------------------------
1 | import CDP from "chrome-remote-interface";
2 | import delay from "./delay.js";
3 |
4 | /**
5 | * @param {CDP.Client} client
6 | */
7 | async function Click(client, sessionId) {
8 | let connected = true
9 | while (connected) {
10 | try {
11 | await delay(1000);
12 |
13 | try {
14 | await client.Target.getTargets();
15 | } catch (error) {
16 | console.log('Client closed');
17 | connected = false
18 | }
19 |
20 | const { nodes } = await client.DOM.getFlattenedDocument(
21 | {
22 | depth: -1,
23 | pierce: true,
24 | },
25 | sessionId
26 | );
27 |
28 | const turnstileNode = nodes.find(
29 | (node) =>
30 | node.nodeName === "IFRAME" &&
31 | node.attributes?.includes("Widget containing a Cloudflare security challenge")
32 | );
33 |
34 | if (!turnstileNode) {
35 | continue;
36 | }
37 |
38 | // Try to get the box model (dimensions) of the node
39 | const location = await client.DOM.getBoxModel(
40 | { nodeId: turnstileNode.nodeId },
41 | sessionId
42 | );
43 | const [x1, y1, x2, y2, x3, y3, x4, y4] = location.model.content;
44 |
45 | // Calculate center
46 | const x = (x1 + x3) / 2;
47 | const y = (y1 + y3) / 2;
48 |
49 | await delay(2000);
50 |
51 | await client.Input.dispatchMouseEvent(
52 | {
53 | type: 'mouseMoved',
54 | x,
55 | y,
56 | },
57 | sessionId
58 | );
59 |
60 | // Press the left mouse button
61 | await client.Input.dispatchMouseEvent(
62 | {
63 | type: 'mousePressed',
64 | x,
65 | y,
66 | button: 'left',
67 | clickCount: 1,
68 | },
69 | sessionId
70 | );
71 |
72 | // Release the left mouse button
73 | await client.Input.dispatchMouseEvent(
74 | {
75 | type: 'mouseReleased',
76 | x,
77 | y,
78 | button: 'left',
79 | clickCount: 1,
80 | },
81 | sessionId
82 | );
83 | } catch (error) {
84 | // Handle errors silently
85 | }
86 | }
87 | }
88 |
89 | export default Click
--------------------------------------------------------------------------------
/lib/ConvertToCDPHeaders.js:
--------------------------------------------------------------------------------
1 | function ConvertToCDPHeaders(headers) {
2 | // Check if headers is a JSON object
3 | if (typeof headers !== 'object' || headers === null || Array.isArray(headers)) {
4 | return undefined
5 | }
6 |
7 | // Convert headers to CDP format
8 | const formattedHeaders = Object.entries(headers)
9 | .map(([key, value]) => `${key}: ${value}`);
10 |
11 | return formattedHeaders;
12 | }
13 |
14 | export default ConvertToCDPHeaders;
--------------------------------------------------------------------------------
/lib/DeleteTempUserDataFolders.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs/promises';
2 | import path from 'path';
3 |
4 | /**
5 | * Delete unused temporary user data folders.
6 | * @param {string} cloudflareBypassDir - The directory path for cloudflare bypass.
7 | */
8 | async function DeleteTempUserDataFolders(cloudflareBypassDir) {
9 | try {
10 | await fs.mkdir(cloudflareBypassDir, { recursive: true });
11 |
12 | const contents = await fs.readdir(cloudflareBypassDir);
13 |
14 | for (const item of contents) {
15 | const itemPath = path.join(cloudflareBypassDir, item);
16 | const stats = await fs.stat(itemPath);
17 |
18 | if (stats.isDirectory() && item.startsWith('CloudFreed_')) {
19 | try {
20 | await fs.rm(itemPath, { recursive: true });
21 | } catch {}
22 | }
23 | }
24 | } catch (error) {
25 | console.error('Error reading directory:', error);
26 | }
27 | }
28 |
29 | export default DeleteTempUserDataFolders
--------------------------------------------------------------------------------
/lib/Extension/background.js:
--------------------------------------------------------------------------------
1 | const ALL_RESOURCE_TYPES = [
2 | 'main_frame',
3 | 'sub_frame',
4 | 'stylesheet',
5 | 'script',
6 | 'image',
7 | 'font',
8 | 'object',
9 | 'xmlhttprequest',
10 | 'ping',
11 | 'csp_report',
12 | 'media',
13 | 'websocket',
14 | 'webtransport',
15 | 'webbundle',
16 | 'other',
17 | ];
18 |
19 | async function setUserAgentOverride(userAgent) {
20 | chrome.declarativeNetRequest.updateDynamicRules({
21 | removeRuleIds: [1], // Remove any existing rule with ID 1
22 | addRules: [
23 | {
24 | id: 1,
25 | priority: 99,
26 | action: {
27 | type: "modifyHeaders",
28 | requestHeaders: [
29 | {
30 | header: "User-Agent",
31 | operation: "set",
32 | value: userAgent
33 | },
34 | {
35 | header: "Accept-Encoding",
36 | operation: "set",
37 | value: ""
38 | },
39 | {
40 | header: "x-Client-Data",
41 | operation: "remove"
42 | },
43 | {
44 | header: "Sec-CH-UA",
45 | operation: "remove"
46 | },
47 | {
48 | header: "Sec-CH-UA-Mobile",
49 | operation: "remove"
50 | },
51 | {
52 | header: "Sec-CH-UA-Platform",
53 | operation: "remove"
54 | },
55 | {
56 | header: "Sec-CH-UA-Platform-Version",
57 | operation: "remove"
58 | },
59 | {
60 | header: "Sec-CH-UA-Arch",
61 | operation: "remove"
62 | },
63 | {
64 | header: "Sec-CH-UA-Model",
65 | operation: "remove"
66 | },
67 | {
68 | header: "Sec-CH-UA-Full-Version",
69 | operation: "remove"
70 | },
71 | {
72 | header: "Sec-CH-UA-Bitness",
73 | operation: "remove"
74 | },
75 | {
76 | header: "Sec-CH-UA-Full-Version-List",
77 | operation: "remove"
78 | },
79 | {
80 | header: "Sec-CH-UA-WoW64",
81 | operation: "remove"
82 | }
83 | ],
84 | responseHeaders: [
85 | {
86 | header: "Cache-Control",
87 | operation: "set",
88 | value: "no-store, no-cache, must-revalidate, proxy-revalidate"
89 | }
90 | ]
91 | },
92 | condition: {
93 | resourceTypes: ALL_RESOURCE_TYPES,
94 | urlFilter: "*"
95 | }
96 | }
97 | ]
98 | });
99 | };
100 |
101 | function updateProxy(proxyConfig) {
102 | if (!proxyConfig || typeof proxyConfig.scheme !== "string" || typeof proxyConfig.host !== "string" || typeof proxyConfig.port !== "number") {
103 | console.error('Invalid proxy configuration:', JSON.stringify(proxyConfig));
104 | return;
105 | }
106 |
107 | chrome.proxy.settings.set(
108 | {
109 | value: {
110 | mode: 'fixed_servers',
111 | rules: {
112 | singleProxy: {
113 | scheme: proxyConfig.scheme,
114 | host: proxyConfig.host,
115 | port: parseInt(proxyConfig.port, 10)
116 | }
117 | }
118 | },
119 | scope: 'regular'
120 | },
121 | () => {
122 | console.log('Proxy updated to:', proxyConfig);
123 | }
124 | );
125 | }
126 |
127 | function clearProxy() {
128 | chrome.proxy.settings.clear({}, function() {
129 | if (chrome.runtime.lastError) {
130 | console.error('Error clearing proxy settings:', chrome.runtime.lastError);
131 | } else {
132 | console.log('Proxy settings cleared successfully.');
133 | }
134 | });
135 | }
136 |
137 | self.consoleMessageHandler = (message) => {
138 | console.log("Received message from DevTools console:", JSON.stringify(message));
139 |
140 | if (typeof message === "object" && message.data && message.type === "modifyData") {
141 | if (message.data.userAgent) {
142 | setUserAgentOverride(message.data.userAgent)
143 | }
144 | if (message.data.proxy) {
145 | updateProxy(message.data.proxy)
146 | } else {
147 | clearProxy()
148 | }
149 | }
150 | };
--------------------------------------------------------------------------------
/lib/Extension/click.js:
--------------------------------------------------------------------------------
1 | async function ShadowFinder() {
2 | const eventNames = [ 'mouseover', 'mouseenter', 'mousedown', 'mouseup', 'click', 'mouseout' ];
3 | const delay = async (milliseconds) => await new Promise(resolve => setTimeout(resolve, milliseconds));
4 | const randomInteger = (n,r) => Math.floor(Math.random()*(r-n+1))+n;
5 | const originalAttachShadow = Element.prototype.attachShadow;
6 | const getBoundingClientRect = (box) => [randomInteger(box.left, box.left + box.width), randomInteger(box.top, box.top + box.height)];
7 | const dispatchEvent = (element, eventName, clientX, clientY) => element.dispatchEvent(new MouseEvent(eventName, { detail: eventName === 'mouseover' ? 0 : 1, view: window, bubbles: true, cancelable: true, clientX, clientY }));
8 | const simulateMouseClick = (element, clientX = null, clientY = null) => {[clientX, clientY] = getBoundingClientRect(element.getBoundingClientRect()); eventNames.forEach((eventName) => dispatchEvent(element, eventName, clientX, clientY))};
9 | const getTargetElement = (shadowRoot) => shadowRoot.querySelector('div[style*="display: grid"] > div > label');
10 | const clickElement = async (element) => {await delay(randomInteger(500, 1000));simulateMouseClick(element);};
11 | const isElementClicked = (element) => {const input = element.querySelector("input");return input && input.getAttribute('aria-checked') !== null;};
12 | const Click = async (shadowRoot) => { while (true) { await delay(100); const element = getTargetElement(shadowRoot); if (element && await clickElement(element) && isElementClicked(element)) return; } };
13 | const definetoString = (Property) => Object.defineProperty(Property, 'toString', { value: function() { return 'function attachShadow() { [native code] }' } });
14 | const attachShadow = (() => {Element.prototype.attachShadow = function(init) {let shadowRoot = originalAttachShadow.call(this, init); Click(shadowRoot); return shadowRoot}; definetoString(Element.prototype.attachShadow)})()
15 | }
16 |
17 | const attachShadowReplacement = "(" + ShadowFinder.toString().replace("ShadowFinder", "") + ")();";
18 | const attachShadowReplacementScript = document.createElement("script")
19 | attachShadowReplacementScript.textContent = attachShadowReplacement
20 | document.documentElement.appendChild(attachShadowReplacementScript)
--------------------------------------------------------------------------------
/lib/Extension/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 3,
3 | "name": "CloudFreed",
4 | "version": "1.0.1",
5 | "permissions": [
6 | "proxy",
7 | "declarativeNetRequest"
8 | ],
9 | "background": {
10 | "service_worker": "background.js"
11 | },
12 | "host_permissions": [
13 | ""
14 | ],
15 | "content_scripts": [
16 | {
17 | "js": [
18 | "./script.js"
19 | ],
20 | "matches": [
21 | ""
22 | ],
23 | "run_at": "document_start",
24 | "all_frames": true,
25 | "world": "MAIN"
26 | },
27 | {
28 | "js": [
29 | "./click.js"
30 | ],
31 | "matches": [
32 | "*://challenges.cloudflare.com/*"
33 | ],
34 | "run_at": "document_start",
35 | "all_frames": true,
36 | "world": "MAIN"
37 | }
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/lib/Extension/proxy.js:
--------------------------------------------------------------------------------
1 | chrome.runtime.sendMessage({ action: "getTabId" }, function(response) {
2 | if (chrome.runtime.lastError || !response?.tabId) {
3 | console.error("Error:", chrome.runtime.lastError.message);
4 | }
5 | originalOpen = XMLHttpRequest.prototype.open
6 | XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
7 | this.addEventListener("readystatechange", function() {
8 | if (this.readyState == 4) {
9 | console.log('ahh')
10 | this.setRequestHeader("x-proxy-agent", "your-header-value");
11 | }
12 | }, false);
13 | console.log('ahh')
14 | originalOpen.call(this, method, url, async, user, pass);
15 | };
16 | });
--------------------------------------------------------------------------------
/lib/Extension/script.js:
--------------------------------------------------------------------------------
1 | delay = async (milliseconds) => await new Promise(resolve => setTimeout(resolve, milliseconds));
2 | getRandomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
3 |
4 | Object.defineProperties(MouseEvent.prototype, {
5 | screenX: { value: getRandomInt(1, 500) },
6 | screenY: { value: getRandomInt(1, 500) }
7 | })
8 |
9 | Object.defineProperties(window, {
10 | chrome: {
11 | value: undefined,
12 | configurable: false,
13 | enumerable: true,
14 | writable: false
15 | }
16 | });
17 |
18 | function NavigatorReplacement() {
19 | Object.defineProperties(NavigatorUAData.prototype, {
20 | getHighEntropyValues: {
21 | value: function () {
22 | return {
23 | "architecture": "x86",
24 | "bitness": "64",
25 | "brands": [
26 | { "brand": "Google Chrome", "version": "129" },
27 | { "brand": "Not=A?Brand", "version": "8" },
28 | { "brand": "Chromium", "version": "129" }
29 | ],
30 | "mobile": false,
31 | "model": "",
32 | "platform": "Windows",
33 | "platformVersion": "15.0.0",
34 | "uaFullVersion": "129.0.6668.58",
35 | "wow64": false
36 | };
37 | },
38 | configurable: false, // You can set this to true if you want to redefine it later
39 | enumerable: true,
40 | writable: false // Prevents the value from being changed
41 | }
42 | });
43 | }
44 |
45 | NavigatorReplacement()
46 |
47 | const navigatorReplacement = "(" + NavigatorReplacement.toString().replace("NavigatorReplacement", "") + ")();";
48 |
49 | const originalBlob = Blob
50 |
51 | Blob = function(blobParts, options) {
52 | if (options && (options.type === "application/javascript" || options.type == "text/javascript")) {
53 | for (let i = 0; i < blobParts.length; i++) {
54 |
55 | }
56 | }
57 |
58 | return new originalBlob(blobParts, options);
59 | };
--------------------------------------------------------------------------------
/lib/FindAvailablePort.js:
--------------------------------------------------------------------------------
1 | import { createServer } from 'net';
2 |
3 | /**
4 | * Checks if a port is available for use.
5 | * @param {number} port - The port number to check.
6 | * @returns {Promise} - A promise that resolves to true if the port is available, false otherwise.
7 | */
8 | async function checkPort(port) {
9 | return new Promise((resolve, reject) => {
10 | const server = createServer();
11 | server.listen(port, () => {
12 | server.close();
13 | resolve(true);
14 | });
15 | server.on('error', (err) => {
16 | if (err.code === 'EADDRINUSE') {
17 | resolve(false);
18 | } else {
19 | reject(err);
20 | }
21 | });
22 | });
23 | }
24 |
25 | /**
26 | * Finds an available port within a specified range.
27 | * @param {number} minPort - The minimum port number in the range.
28 | * @param {number} maxPort - The maximum port number in the range.
29 | * @returns {Promise} - A promise that resolves to the available port number found within the specified range.
30 | */
31 | async function FindAvailablePort(minPort, maxPort) {
32 | while (true) {
33 | const port = Math.floor(Math.random() * (maxPort - minPort + 1)) + minPort;
34 | if (await checkPort(port)) {
35 | return port;
36 | }
37 | }
38 | }
39 |
40 | export default FindAvailablePort
--------------------------------------------------------------------------------
/lib/GetDefaultChromePath.js:
--------------------------------------------------------------------------------
1 | import os from "os";
2 |
3 | function GetDefaultChromePath() {
4 | const platform = os.platform();
5 |
6 | switch(platform) {
7 | case 'win32':
8 | if (process.arch === 'x64') {
9 | return 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe';
10 | } else {
11 | // Default path to Chrome on 32-bit Windows
12 | return 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe';
13 | }
14 | case 'darwin':
15 | // Default path to Chrome on macOS
16 | return '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
17 | case 'linux':
18 | // Default path to Chrome on Linux
19 | return '/usr/bin/google-chrome';
20 | default:
21 | return null; // Unsupported platform
22 | }
23 | }
24 |
25 | export default GetDefaultChromePath
--------------------------------------------------------------------------------
/lib/GetHomeDirectory.js:
--------------------------------------------------------------------------------
1 | import os from "os"
2 |
3 | function GetHomeDirectory() {
4 | const platform = os.platform();
5 |
6 | switch(platform) {
7 | case 'win32':
8 | return process.env.USERPROFILE !== undefined ? process.env.USERPROFILE : null; // On Windows
9 | case 'darwin':
10 | return process.env.HOME !== undefined ? process.env.HOME : null; // On macOS
11 | case 'linux':
12 | return process.env.HOME !== undefined ? process.env.HOME : null; // On Linux
13 | default:
14 | return null; // Unsupported platform
15 | }
16 | }
17 |
18 | export default GetHomeDirectory
--------------------------------------------------------------------------------
/lib/KillProcess.js:
--------------------------------------------------------------------------------
1 | import { spawn } from "child_process";
2 |
3 | function KillProcess(pid) {
4 | return new Promise((resolve, reject) => {
5 | const platform = process.platform;
6 | const command = (platform === 'win32') ? 'taskkill' : 'kill';
7 | const args = (platform === 'win32') ? ['/F', '/PID', pid.toString(), '/T'] : ['-9', pid.toString()];
8 |
9 | const killProc = spawn(command, args);
10 |
11 | killProc.on('close', (code) => {
12 | if (code === 0) {
13 | resolve();
14 | } else {
15 | resolve(new Error(`Failed to kill process ${pid}. Exit code: ${code}`));
16 | }
17 | });
18 |
19 | killProc.on('error', (err) => {
20 | resolve(new Error(`Error killing process ${pid}: ${err.message}`));
21 | });
22 | });
23 | }
24 |
25 | export default KillProcess;
--------------------------------------------------------------------------------
/lib/Proxy.js:
--------------------------------------------------------------------------------
1 | import { HttpProxyAgent } from "http-proxy-agent";
2 | import { HttpsProxyAgent } from "https-proxy-agent";
3 | import { SocksProxyAgent } from "socks-proxy-agent";
4 |
5 | class Proxy {
6 | constructor({ http, https, socks }) {
7 | if (http) {
8 | this.agent = new HttpProxyAgent(http);
9 | } else if (https) {
10 | this.agent = new HttpsProxyAgent(https);
11 | } else if (socks) {
12 | this.agent = new SocksProxyAgent(socks);
13 | } else {
14 | throw new Error("Invalid proxy type. Please provide either an http, https, or socks proxy.");
15 | }
16 | }
17 |
18 | getAgent() {
19 | return this.agent;
20 | }
21 | }
22 |
23 | export default Proxy;
--------------------------------------------------------------------------------
/lib/Solve copy.js:
--------------------------------------------------------------------------------
1 | import delay from "./delay.js";
2 | import { readFile, writeFile } from "./fs.js";
3 | import path from "path";
4 | import curl from "./curl.js"
5 | import { fileURLToPath } from 'url';
6 | import CDP from "chrome-remote-interface";
7 |
8 | const __dirname = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
9 |
10 | // Load all required files asynchronously
11 | const [IUAMHTML, invisibleHTML] = await Promise.all([
12 | path.join(__dirname, "html", "CloudFreed.html"),
13 | readFile(path.join(__dirname, "html", "IUAMChallenge.html")),
14 | readFile(path.join(__dirname, "html", "InvisibleChallenge.html"))
15 | ]);
16 |
17 | const TurnstileHTML = await readFile(path.join(__dirname, "html", "TurnstileChallenge.html"))
18 | const RecaptchaHTML = await readFile(path.join(__dirname, "html", "RecaptchaInvisibleChallenge.html"))
19 | const blockResourceTypes = ["Image", "Font", "Stylesheet", "Other", "Media"];
20 | const invalidTypes = ["V3", "IUAM", "Turnstile", "Invisible", "RecaptchaInvisible"];
21 |
22 | // Generate HTML templates with dynamic values
23 | const generateInvisibleHTML = (r, t) => invisibleHTML.replace("![r]!", r).replace("![t]!", t);
24 | const generateTurnstileHTML = (sitekey) => TurnstileHTML.replace("![sitekey]!", sitekey);
25 | const generateRecaptchaHTML = (sitekey) => RecaptchaHTML.replace(/!\[sitekey\]!/g, sitekey);
26 | const generateIUAMHTML = (script) => IUAMHTML.replace("![script]!", script);
27 |
28 | /**
29 | * @param {CDP.Client} client
30 | * @param {Object} data
31 | * @param {string} data.url - The URL to request.
32 | * @param {string} data.type - The request type (e.g., GET, POST).
33 | * @param {string|undefined} data.sitekey - The site key, if applicable.
34 | * @param {string|undefined} data.userAgent - The User-Agent string to use, if applicable.
35 | * @param {{ scheme:string, host:string, port:number, username:string|undefined, password:string|undefined }} data.proxy - The proxy configuration object, if applicable.
36 | * @param {string} sessionId
37 | * @param {string} originalUserAgent
38 | * @param {string} extensionSessionId
39 | * @param {boolean} proxyOverride
40 | */
41 | async function Solve(client, data, sessionId, originalUserAgent, extensionSessionId, proxyOverride) {
42 | return new Promise(async (resolve, reject) => {
43 | try {
44 | let listenerComplete = false;
45 |
46 | if (typeof client !== "object" || typeof data !== "object" || typeof sessionId !== "string" || !invalidTypes.includes(data.type) || !data.url || typeof data.url !== "string") {
47 | resolve({success: false, code: 500, errormessage: "Solve function received invalid parameters, please contact a dev."})
48 | return;
49 | }
50 |
51 | if (typeof data.userAgent !== "string") {
52 | data.userAgent = originalUserAgent
53 | }
54 |
55 | client.Network.setUserAgentOverride({ userAgent: data.userAgent })
56 | client.Emulation.setUserAgentOverride({ userAgent: data.userAgent })
57 |
58 | if (typeof data.proxy === "object" && typeof data.proxy.scheme === "string" && typeof data.proxy.host === "string" && typeof data.proxy.port === "number" && data.proxy.port > 0) {
59 | await client.Runtime.evaluate({
60 | expression: `consoleMessageHandler(${JSON.stringify({ type: "modifyData", data: { proxy: data.proxy, userAgent: data.userAgent }})});`
61 | }, extensionSessionId);
62 |
63 | await delay(100);
64 | } else if (data.proxy === undefined) {
65 | await client.Runtime.evaluate({
66 | expression: `consoleMessageHandler(${JSON.stringify({ type: "modifyData", data: { userAgent: data.userAgent }})});`
67 | }, extensionSessionId);
68 |
69 | await delay(100);
70 | } else {
71 | resolve({
72 | success: false,
73 | code: 500,
74 | errormessage: "Proxy entered is invalid, please check your parameters and try again."
75 | });
76 | return;
77 | }
78 |
79 | await client.Network.clearBrowserCookies(sessionId);
80 |
81 | if (data.type === "V3" || data.type === "IUAM") {
82 | if (proxyOverride !== true && (!data.proxy || !data.proxy.scheme || !data.proxy.host || typeof data.proxy.port !== "number")) {
83 | resolve({
84 | success: false,
85 | code: 500,
86 | errormessage: "A Proxy is required for this type of solve, please enter a proxy into your request and try again."
87 | });
88 | return;
89 | }
90 |
91 | const proxyUrl = data.proxy && data.proxy.scheme && data.proxy.host && data.proxy.port
92 | ? `${data.proxy.scheme}://${data.proxy.username && data.proxy.password
93 | ? `${data.proxy.username}:${data.proxy.password}@`
94 | : ''}${data.proxy.host}:${data.proxy.port}`
95 | : undefined;
96 |
97 | // Construct headers if user agent is provided
98 | const headers = data.userAgent ? ['-H', `User-Agent: ${data.userAgent}`] : undefined;
99 |
100 | // Perform the HTTP request
101 | let html = await curl(data.url, "GET", proxyUrl, headers);
102 |
103 | if (!html.success) {
104 | resolve({
105 | success: false,
106 | code: html.code,
107 | cerror: html.err ? html.err : undefined,
108 | error: html.error ? html.error : undefined,
109 | errormessage: html.errormessage ? html.errormessage : "Unknown error occurred, please contact a dev."
110 | });
111 | return;
112 | }
113 |
114 | if (html.redirected) {
115 | resolve({
116 | success: false,
117 | code: 400,
118 | cerror: html.err ? html.err : undefined,
119 | errormessage: "Given URL leads to a redirect, please enter a URL that returns a cloudflare challenge."
120 | });
121 | return;
122 | }
123 |
124 | if (typeof html !== "object" || typeof html.response !== "string" || html.status !== 403 || !html.response.includes('')) {
125 | resolve({
126 | success: false,
127 | code: 400,
128 | cerror: html.err ? html.err : undefined,
129 | errormessage: "Failed to find IUAM challenge. Check the URL or proxy."
130 | });
131 | return;
132 | }
133 |
134 | client.Network.responseReceivedExtraInfo(async ( response ) => {
135 | try {
136 | const setCookieHeader = response.headers['set-cookie']
137 |
138 | // Check and log Set-Cookie headers
139 | if (setCookieHeader && response.headers['content-length'] === '0' && setCookieHeader.includes("cf_clearance") && setCookieHeader.includes("\n")) {
140 | const cookie = setCookieHeader.split("\n")[1];
141 |
142 | resolve({ success: true, code: 200, cfClearance: cookie, ...data });
143 | return;
144 | }
145 | } catch (error) {
146 | console.error(error)
147 | // Resolve errors silently
148 | }
149 | }, sessionId);
150 |
151 | await client.Network.setRequestInterception({
152 | patterns: [
153 | { urlPattern: "*" },
154 | { urlPattern: "*", interceptionStage: "HeadersReceived" }
155 | ]
156 | }, sessionId);
157 |
158 | client.Network.requestIntercepted(async (listener) => {
159 | try {
160 | const continueRequest = async (options = {}) => {
161 | try {
162 | await client.Network.continueInterceptedRequest({
163 | interceptionId: listener.interceptionId,
164 | ...options,
165 | }, sessionId);
166 | } catch {}
167 | };
168 |
169 | const getBody = async () => {
170 | try {
171 | const body = await client.Network.getResponseBodyForInterception({ interceptionId: listener.interceptionId }, sessionId);
172 | return body.base64Encoded ? Buffer.from(body.body, "base64").toString("utf-8") : body.body;
173 | } catch {}
174 | };
175 |
176 | if (listener.authChallenge) {
177 | if (!data.proxy.username || !data.proxy.password) {
178 | resolve({
179 | success: false,
180 | code: 500,
181 | errormessage: "Proxy Provided requires a Username & Password, request is missing one or more of these parameters."
182 | });
183 | return;
184 | }
185 |
186 | await continueRequest({
187 | authChallengeResponse: {
188 | response: "ProvideCredentials",
189 | username: data.proxy.username,
190 | password: data.proxy.password,
191 | }
192 | });
193 | return;
194 | }
195 |
196 | if (blockResourceTypes.includes(listener.resourceType)) {
197 | await continueRequest({
198 | rawResponse: Buffer.from('HTTP/2 404 CloudFreed Stopped media\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n\r\n').toString('base64')
199 | });
200 | return;
201 | }
202 |
203 | if (listener.request.url === data.url && listener.responseHeaders) {
204 | if (listener.request.method === "GET") {
205 | let body = await getBody()
206 | if (body.includes('')) {
207 | const string = body.split('')[1].split('')[0];
208 | let html = generateIUAMHTML(string);
209 |
210 | await continueRequest({
211 | rawResponse: Buffer.from(`HTTP/2 200 OK\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n${html}`).toString('base64')
212 | });
213 | return;
214 | }
215 |
216 | await continueRequest();
217 | return;
218 | }
219 |
220 | if (listener.request.method === "POST") {
221 | const t = Buffer.from(Math.floor(Date.now() / 1000).toString() + ".000000").toString("base64");
222 | const r = listener.responseHeaders["cf-ray"].split('-')[0] ? listener.responseHeaders["cf-ray"].split('-')[0] : ""
223 | await continueRequest({
224 | rawResponse: Buffer.from(`HTTP/2 200 OK\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n${generateInvisibleHTML(r, t)}`).toString('base64')
225 | });
226 | return;
227 | }
228 | }
229 |
230 | await continueRequest();
231 | } catch (error) {
232 | console.log(error)
233 | // Resolve errors silently
234 | }
235 | });
236 |
237 | await client.Page.navigate({ url: data.url }, sessionId)
238 | }
239 |
240 | if (data.type === "Turnstile") {
241 | await client.Network.setRequestInterception({
242 | patterns: [
243 | { urlPattern: "*" }
244 | ]
245 | }, sessionId);
246 |
247 | client.Network.requestIntercepted(async (listener) => {
248 | try {
249 | console.log(listenerComplete)
250 | if (listenerComplete) return;
251 |
252 | const continueRequest = async (options = {}) => {
253 | try {
254 | await client.Network.continueInterceptedRequest({
255 | interceptionId: listener.interceptionId,
256 | ...options,
257 | }, sessionId);
258 | } catch(error) {console.log(error)}
259 | };
260 |
261 | if (listener.authChallenge) {
262 | if (!data.proxy.username || !data.proxy.password) {
263 | resolve({
264 | success: false,
265 | code: 500,
266 | errormessage: "Proxy Provided requires a Username & Password, request is missing one or more of these parameters."
267 | });
268 | return;
269 | }
270 |
271 | await continueRequest({
272 | authChallengeResponse: {
273 | response: "ProvideCredentials",
274 | username: data.proxy.username,
275 | password: data.proxy.password,
276 | }
277 | });
278 | return;
279 | }
280 |
281 | if (blockResourceTypes.includes(listener.resourceType)) {
282 | await continueRequest({
283 | rawResponse: Buffer.from('HTTP/2 404 CloudFreed Stopped media\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n\r\n').toString('base64')
284 | });
285 | return;
286 | }
287 |
288 | if (listener.request.url === data.url) {
289 | await continueRequest({
290 | rawResponse: Buffer.from('HTTP/2 200 OK\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n' + generateTurnstileHTML(data.sitekey)).toString('base64')
291 | });
292 | return;
293 | }
294 |
295 | if (listener.request.url === "https://internals.cloudfreed.com/turnstile") {
296 | await continueRequest()
297 | listenerComplete = true
298 | resolve({success: true, code: 200, response: listener.request.postData})
299 | return;
300 | }
301 |
302 | await continueRequest();
303 | } catch (error) {
304 | console.error(error)
305 | // Resolve errors silently
306 | }
307 | });
308 |
309 | await client.Page.navigate({ url: data.url }, sessionId)
310 | }
311 |
312 | if (data.type === "Invisible") {
313 | if (proxyOverride !== true && (!data.proxy || !data.proxy.scheme || !data.proxy.host || typeof data.proxy.port !== "number")) {
314 | resolve({
315 | success: false,
316 | code: 500,
317 | errormessage: "A Proxy is required for this type of solve, please enter a proxy into your request and try again."
318 | });
319 | return;
320 | }
321 |
322 | client.Network.responseReceivedExtraInfo(async ( response ) => {
323 | try {
324 | const setCookieHeader = response.headers['set-cookie']
325 |
326 | // Check and log Set-Cookie headers
327 | if (setCookieHeader && response.headers['content-length'] === '0' && setCookieHeader.includes("cf_clearance") && setCookieHeader.includes("\n")) {
328 | const cookie = setCookieHeader.split("\n")[1];
329 |
330 | resolve({ success: true, code: 200, cfClearance: cookie, ...data });
331 | return;
332 | }
333 | } catch (error) {
334 | console.error(error)
335 | // Resolve errors silently
336 | }
337 | }, sessionId);
338 |
339 | await client.Network.setRequestInterception({
340 | patterns: [
341 | { urlPattern: "*" },
342 | { urlPattern: data.url, interceptionStage: "HeadersReceived" }
343 | ]
344 | }, sessionId);
345 |
346 | client.Network.requestIntercepted(async (listener) => {
347 | try {
348 | const continueRequest = async (options = {}) => {
349 | try {
350 | await client.Network.continueInterceptedRequest({
351 | interceptionId: listener.interceptionId,
352 | ...options,
353 | }, sessionId);
354 | } catch {}
355 | };
356 |
357 | if (listener.authChallenge) {
358 | if (!data.proxy.username || !data.proxy.password) {
359 | resolve({
360 | success: false,
361 | code: 500,
362 | errormessage: "Proxy Provided requires a Username & Password, request is missing one or more of these parameters."
363 | });
364 | return;
365 | }
366 |
367 | await continueRequest({
368 | authChallengeResponse: {
369 | response: "ProvideCredentials",
370 | username: data.proxy.username,
371 | password: data.proxy.password,
372 | }
373 | });
374 | return;
375 | }
376 |
377 | if (blockResourceTypes.includes(listener.resourceType)) {
378 | await continueRequest({
379 | rawResponse: Buffer.from('HTTP/2 404 CloudFreed Stopped media\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n\r\n').toString('base64')
380 | });
381 | return;
382 | }
383 |
384 | if (listener.request.url === data.url && listener.responseHeaders) {
385 | const t = Buffer.from(Math.floor(Date.now() / 1000).toString() + ".000000").toString("base64");
386 | const r = listener.responseHeaders["cf-ray"].split('-')[0] ? listener.responseHeaders["cf-ray"].split('-')[0] : ""
387 |
388 | await continueRequest({
389 | rawResponse: Buffer.from(`HTTP/2 200 OK\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n${generateInvisibleHTML(r, t)}`).toString('base64')
390 | });
391 | }
392 |
393 | await continueRequest();
394 | } catch (error) {
395 | // Resolve errors silently
396 | }
397 | });
398 |
399 | await client.Page.navigate({ url: data.url }, sessionId)
400 | }
401 |
402 | if (data.type === "RecaptchaInvisible") {
403 | await client.Network.setRequestInterception({
404 | patterns: [
405 | { urlPattern: "*" }
406 | ]
407 | }, sessionId);
408 |
409 | client.Network.requestIntercepted(async (listener) => {
410 | try {
411 | const continueRequest = async (options = {}) => {
412 | try {
413 | await client.Network.continueInterceptedRequest({
414 | interceptionId: listener.interceptionId,
415 | ...options,
416 | }, sessionId);
417 | } catch(error) {console.log(error)}
418 | };
419 |
420 | if (listener.authChallenge) {
421 | if (!data.proxy.username || !data.proxy.password) {
422 | resolve({
423 | success: false,
424 | code: 500,
425 | errormessage: "Proxy Provided requires a Username & Password, request is missing one or more of these parameters."
426 | });
427 | return;
428 | }
429 |
430 | await continueRequest({
431 | authChallengeResponse: {
432 | response: "ProvideCredentials",
433 | username: data.proxy.username,
434 | password: data.proxy.password,
435 | }
436 | });
437 | return;
438 | }
439 |
440 | if (blockResourceTypes.includes(listener.resourceType)) {
441 | await continueRequest({
442 | rawResponse: Buffer.from('HTTP/2 404 CloudFreed Stopped media\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n\r\n').toString('base64')
443 | });
444 | return;
445 | }
446 |
447 | if (listener.request.url === data.url) {
448 | await continueRequest({
449 | rawResponse: Buffer.from('HTTP/2 200 OK\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n' + generateRecaptchaHTML(data.sitekey)).toString('base64')
450 | });
451 | return;
452 | }
453 |
454 | if (listener.request.url === "https://internals.cloudfreed.com/turnstile") {
455 | await continueRequest()
456 | resolve({success: true, code: 200, response: listener.request.postData})
457 | return;
458 | }
459 |
460 | await continueRequest();
461 | } catch (error) {
462 | console.error(error)
463 | // Resolve errors silently
464 | }
465 | });
466 |
467 | await client.Page.navigate({ url: data.url }, sessionId)
468 | }
469 | } catch (error) {
470 | try {
471 | await client.Network.setRequestInterception({ patterns: [] }, sessionId);
472 |
473 | resolve({
474 | success: false,
475 | code: 500,
476 | errormessage: "An error occurred on our side. Please check your request or try again later.",
477 | error
478 | });
479 | return;
480 | } catch (error) {
481 | resolve({
482 | success: false,
483 | code: 500,
484 | errormessage: "An error occurred on our side. Please check your request or try again later.",
485 | error
486 | });
487 | return;
488 | }
489 | }
490 | })
491 | }
492 |
493 | export default Solve
--------------------------------------------------------------------------------
/lib/Solve.js:
--------------------------------------------------------------------------------
1 | import delay from "./delay.js";
2 | import { readFile, writeFile } from "./fs.js";
3 | import path from "path";
4 | import curl from "./curl.js"
5 | import { fileURLToPath } from 'url';
6 | import CDP from "chrome-remote-interface";
7 |
8 | const __dirname = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
9 |
10 | // Load all required files asynchronously
11 | const [IUAMHTML, invisibleHTML, TurnstileHTML, RecaptchaHTML] = await Promise.all([
12 | readFile(path.join(__dirname, "html", "IUAMChallenge.html")),
13 | readFile(path.join(__dirname, "html", "InvisibleChallenge.html")),
14 | readFile(path.join(__dirname, "html", "TurnstileChallenge.html")),
15 | readFile(path.join(__dirname, "html", "RecaptchaInvisibleChallenge.html"))
16 | ]);
17 |
18 | const blockResourceTypes = ["Image", "Font", "Stylesheet", "Other", "Media"];
19 | const invalidTypes = ["V3", "IUAM", "Turnstile", "Invisible", "RecaptchaInvisible"];
20 |
21 | // Generate HTML templates with dynamic values
22 | const generateInvisibleHTML = (r, t) => invisibleHTML.replace("![r]!", r).replace("![t]!", t);
23 | const generateTurnstileHTML = (sitekey) => TurnstileHTML.replace("![sitekey]!", sitekey);
24 | const generateRecaptchaHTML = (sitekey, action) => RecaptchaHTML.replace(/!\[sitekey\]!/g, sitekey).replace("![action]!", action);
25 | const generateIUAMHTML = (script) => IUAMHTML.replace("![script]!", script);
26 |
27 | class Solve {
28 | constructor(client, sessionId, originalUserAgent, extensionSessionId, proxyOverride) {
29 | this.client = client
30 | this.sessionId = sessionId
31 | this.originalUserAgent = originalUserAgent
32 | this.extensionSessionId = extensionSessionId
33 | this.proxyOverride = proxyOverride
34 |
35 | this.resolve = undefined
36 | this.proxyUrl = undefined
37 | this.iframeBody = undefined
38 | this.iframeURL = undefined
39 | this.data = undefined
40 |
41 | this.continueRequest = async (listener, options = {}) => {
42 | try {
43 | if (options.rawResponse === undefined) {
44 |
45 | }
46 |
47 | await this.client.Network.continueInterceptedRequest({
48 | interceptionId: listener.interceptionId,
49 | ...options,
50 | }, this.sessionId);
51 | } catch {}
52 | };
53 |
54 | this.getBody = async (listener) => {
55 | try {
56 | const body = await this.client.Network.getResponseBodyForInterception({ interceptionId: listener.interceptionId }, this.sessionId);
57 | return body.base64Encoded ? Buffer.from(body.body, "base64").toString("utf-8") : body.body;
58 | } catch {}
59 | };
60 |
61 | this.InterceptedIUAM = async (listener) => {
62 | try {
63 | if (listener.authChallenge) {
64 | if (!this.data.proxy.username || !this.data.proxy.password) {
65 | this.resolve?.({
66 | success: false,
67 | code: 500,
68 | data: this.data,
69 | errormessage: "Proxy Provided requires a Username & Password, request is missing one or more of these parameters."
70 | });
71 | return;
72 | }
73 |
74 | await this.continueRequest(listener, {
75 | authChallengeResponse: {
76 | response: "ProvideCredentials",
77 | username: this.data.proxy.username,
78 | password: this.data.proxy.password,
79 | }
80 | });
81 | return;
82 | }
83 |
84 | if (blockResourceTypes.includes(listener.resourceType)) {
85 | await this.continueRequest(listener, {
86 | rawResponse: Buffer.from('HTTP/2 404 CloudFreed Stopped media\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n\r\n').toString('base64')
87 | });
88 | return;
89 | }
90 |
91 | if (listener.request.url === this.data.url && listener.responseHeaders) {
92 | if (listener.request.method === "GET") {
93 | let body = await this.getBody(listener)
94 | if (body?.includes('')) {
95 | const string = body.split('')[1].split('')[0];
96 | let html = generateIUAMHTML(string);
97 |
98 | await this.continueRequest(listener, {
99 | rawResponse: Buffer.from(`HTTP/2 200 OK\r\nContent-Type: text/html\r\nCross-Origin-Embedder-Policy: require-corp\r\nCross-Origin-Opener-Policy: same-origin\r\nContent-Length: 0\r\n\r\n${html}`).toString('base64')
100 | });
101 | return;
102 | }
103 |
104 | await this.continueRequest(listener);
105 | return;
106 | }
107 |
108 | if (listener.request.method === "POST") {
109 | const t = Buffer.from(Math.floor(Date.now() / 1000).toString() + ".000000").toString("base64");
110 | const r = listener.responseHeaders["cf-ray"].split('-')[0] ? listener.responseHeaders["cf-ray"].split('-')[0] : ""
111 | await this.continueRequest(listener, {
112 | rawResponse: Buffer.from(`HTTP/2 200 OK\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n${generateInvisibleHTML(r, t)}`).toString('base64')
113 | });
114 | return;
115 | }
116 | }
117 |
118 | await this.continueRequest(listener);
119 | } catch (error) {
120 | console.log(error)
121 | // Resolve errors silently
122 | }
123 | }
124 |
125 | this.InterceptedTurnstile = async (listener) => {
126 | try {
127 | if (listener.responseHeaders) {
128 | await this.continueRequest(listener);
129 | }
130 |
131 | if (listener.authChallenge) {
132 | if (!this.data?.proxy?.username || !this.data?.proxy?.password) {
133 | this.resolve?.({
134 | success: false,
135 | code: 500,
136 | data: this.data,
137 | errormessage: "Proxy Provided requires a Username & Password, request is missing one or more of these parameters."
138 | });
139 | return;
140 | }
141 |
142 | await this.continueRequest(listener, {
143 | authChallengeResponse: {
144 | response: "ProvideCredentials",
145 | username: this.data.proxy.username,
146 | password: this.data.proxy.password,
147 | }
148 | });
149 | return;
150 | }
151 |
152 | if (blockResourceTypes.includes(listener.resourceType)) {
153 | await this.continueRequest(listener, {
154 | rawResponse: Buffer.from('HTTP/2 404 CloudFreed Stopped media\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n\r\n').toString('base64')
155 | });
156 | return;
157 | }
158 |
159 | if (listener.request.url === this.data.url) {
160 | await this.continueRequest(listener, {
161 | rawResponse: Buffer.from('HTTP/2 200 OK\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n' + generateTurnstileHTML(this.data.sitekey)).toString('base64')
162 | });
163 | return;
164 | }
165 |
166 | if (listener.request.url === "https://internals.cloudfreed.com/turnstile") {
167 | if (listener.request.method === "OPTIONS") {
168 | await this.continueRequest(listener, {
169 | rawResponse: Buffer.from('HTTP/2 204 No Content\r\nAllow: POST, OPTIONS\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS\r\nAccess-Control-Allow-Headers: Content-Type, Authorization\r\n\r\n').toString("base64")
170 | })
171 | return;
172 | }
173 |
174 | await this.continueRequest(listener)
175 |
176 | this.resolve?.({success: true, code: 200, data: this.data, response: listener.request.postData})
177 | return;
178 | }
179 |
180 | await this.continueRequest(listener);
181 | } catch (error) {
182 | console.error(error)
183 | // Resolve errors silently
184 | }
185 | }
186 |
187 | this.InterceptedInvisible = async (listener) => {
188 | try {
189 | if (listener.authChallenge) {
190 | if (!this.data?.proxy?.username || !this.data?.proxy?.password) {
191 | this.resolve?.({
192 | success: false,
193 | code: 500,
194 | data: this.data,
195 | errormessage: "Proxy Provided requires a Username & Password, request is missing one or more of these parameters."
196 | });
197 | return;
198 | }
199 |
200 | await this.continueRequest(listener, {
201 | authChallengeResponse: {
202 | response: "ProvideCredentials",
203 | username: this.data.proxy.username,
204 | password: this.data.proxy.password,
205 | }
206 | });
207 | return;
208 | }
209 |
210 | if (blockResourceTypes.includes(listener.resourceType)) {
211 | await this.continueRequest(listener, {
212 | rawResponse: Buffer.from('HTTP/2 404 CloudFreed Stopped media\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n\r\n').toString('base64')
213 | });
214 | return;
215 | }
216 |
217 | if (listener.request.url === this.data.url && listener.responseHeaders) {
218 | const t = Buffer.from(Math.floor(Date.now() / 1000).toString() + ".000000").toString("base64");
219 | const r = listener.responseHeaders["cf-ray"].split('-')[0] ? listener.responseHeaders["cf-ray"].split('-')[0] : ""
220 |
221 | await this.continueRequest(listener, {
222 | rawResponse: Buffer.from(`HTTP/2 200 OK\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n${generateInvisibleHTML(r, t)}`).toString('base64')
223 | });
224 | }
225 |
226 | await this.continueRequest(listener);
227 | } catch (error) {
228 | // Resolve errors silently
229 | }
230 | }
231 |
232 | this.InterceptedRecaptchaInvisible = async (listener) => {
233 | try {
234 | if (listener.responseHeaders) {
235 | await this.continueRequest(listener);
236 | }
237 |
238 | if (listener.authChallenge) {
239 | if (!this.data?.proxy?.username || !this.data?.proxy?.password) {
240 | this.resolve?.({
241 | success: false,
242 | code: 500,
243 | data: this.data,
244 | errormessage: "Proxy Provided requires a Username & Password, request is missing one or more of these parameters."
245 | });
246 | return;
247 | }
248 |
249 | await this.continueRequest(listener, {
250 | authChallengeResponse: {
251 | response: "ProvideCredentials",
252 | username: this.data.proxy.username,
253 | password: this.data.proxy.password,
254 | }
255 | });
256 | return;
257 | }
258 |
259 | if (blockResourceTypes.includes(listener.resourceType)) {
260 | await this.continueRequest(listener, {
261 | rawResponse: Buffer.from('HTTP/2 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n\r\n').toString('base64')
262 | });
263 | return;
264 | }
265 |
266 | if (listener.request.url === this.data.url) {
267 | await this.continueRequest(listener, {
268 | rawResponse: Buffer.from('HTTP/2 200 OK\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n' + generateRecaptchaHTML(this.data.sitekey, this.data.action)).toString('base64')
269 | });
270 | return;
271 | }
272 |
273 | if (listener.request.url === "https://internals.cloudfreed.com/turnstile") {
274 | if (listener.request.method === "OPTIONS") {
275 | await this.continueRequest(listener, {
276 | rawResponse: Buffer.from('HTTP/2 204 No Content\r\nAllow: POST, OPTIONS\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS\r\nAccess-Control-Allow-Headers: Content-Type, Authorization\r\n\r\n').toString("base64")
277 | })
278 | return;
279 | }
280 |
281 | await this.continueRequest(listener)
282 |
283 | this.resolve?.({success: true, code: 200, data: this.data, response: listener.request.postData})
284 | return;
285 | }
286 |
287 | await this.continueRequest(listener);
288 | } catch (error) {
289 | console.error(error)
290 | // Resolve errors silently
291 | }
292 | }
293 |
294 | this.Intercepted = async ( listener ) => {
295 | try {
296 | //console.log(listener)
297 | if (blockResourceTypes.includes(listener.resourceType)) {
298 | await this.continueRequest(listener, {
299 | rawResponse: Buffer.from('HTTP/2 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n\r\n').toString('base64')
300 | });
301 |
302 | return;
303 | }
304 |
305 | if (typeof this.data?.type !== "string") {
306 | await this.continueRequest(listener);
307 |
308 | return;
309 | }
310 | /*
311 | let reqheaders = listener.request.headers, headers = []
312 |
313 | for (const [name, value] of Object.entries(reqheaders)) {
314 | if (name.toLowerCase() === "user-agent" || name.toLowerCase().includes("-ch-")) continue;
315 | headers.push('-H', `"${name}: ${value}"`)
316 | }
317 |
318 | console.log(headers)
319 |
320 | listener.response = await curl(listener.request.url, listener.request.method, this.proxyUrl, headers);
321 |
322 | if (!this.data || !this.data?.type || !this.resolve) return this.continueRequest(listener);
323 |
324 | if (listener.responseHeaders && listener.request.url.includes('challenges.cloudflare.com') && listener.resourceType === "Document") {
325 | this.iframeBody = await this.getBody(listener)
326 | this.iframeURL = this.data.url + listener.request.url.split('challenges.cloudflare.com/')[1]
327 |
328 | return this.continueRequest(listener, { rawResponse: Buffer.from(`HTTP/2 302 Found\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: 0\r\nLocation: ${this.iframeURL}\r\n\r\n`).toString("base64") });
329 | }
330 |
331 | if (listener.request.url === this.iframeURL) {
332 | return this.continueRequest(listener, { rawResponse: Buffer.from(`HTTP/2 200 OK\r\ncross-origin-embedder-policy: require-corp\r\ncross-origin-opener-policy: same-origin\r\ncross-origin-resource-policy: cross-origin\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n${this.iframeBody}`).toString("base64") });
333 | }
334 |
335 | if (listener.request.headers['Referer'] === this.iframeURL) {
336 |
337 | }*/
338 |
339 |
340 | switch (this.data.type) {
341 | case "IUAM":
342 | case "V3":
343 | this.InterceptedIUAM(listener);
344 | break;
345 | case "Turnstile":
346 | this.InterceptedTurnstile(listener);
347 | break;
348 | case "Invisible":
349 | this.InterceptedInvisible(listener);
350 | break;
351 | case "RecaptchaInvisible":
352 | this.InterceptedRecaptchaInvisible(listener);
353 | break;
354 | default:
355 | this.continueRequest(listener);
356 | }
357 | } catch (error) {console.error(error)}
358 | }
359 |
360 | this.Extra = async ( response ) => {
361 | try {
362 | const setCookieHeader = response.headers['set-cookie']
363 |
364 | // Check and log Set-Cookie headers
365 | if (setCookieHeader && response.headers['content-length'] === '0' && setCookieHeader.includes("cf_clearance") && setCookieHeader.includes("\n")) {
366 | const cookie = setCookieHeader.split("\n")[1];
367 |
368 | this.resolve?.({ success: true, code: 200, response: cookie, data: this.data });
369 | return;
370 | }
371 | } catch (error) {
372 | console.error(error)
373 | // Resolve errors silently
374 | }
375 | }
376 |
377 | this.client.Network.requestIntercepted(listener => this.Intercepted?.(listener), this.sessionId);
378 | this.client.Network.responseReceivedExtraInfo(response => this.Extra?.(response), this.sessionId);
379 | this.client.Network.setRequestInterception({ patterns: [{ urlPattern: "*" }, { urlPattern: "*", interceptionStage: "HeadersReceived" }] }, this.sessionId);
380 | }
381 |
382 | /**
383 | * @param {CDP.Client} client
384 | * @param {Object} data
385 | * @param {string} data.url - The URL to request.
386 | * @param {string} data.type - The request type (e.g., GET, POST).
387 | * @param {string|undefined} data.sitekey - The site key, if applicable.
388 | * @param {string|undefined} data.userAgent - The User-Agent string to use, if applicable.
389 | * @param {{ scheme:string, host:string, port:number, username:string|undefined, password:string|undefined }} data.proxy - The proxy configuration object, if applicable.
390 | * @param {string} sessionId
391 | * @param {string} originalUserAgent
392 | * @param {string} extensionSessionId
393 | * @param {boolean} proxyOverride
394 | */
395 | async Solve(data, client) {
396 | return new Promise(async (resolve, reject) => {
397 | try {
398 | if (typeof this.client !== "object" || typeof data !== "object" || typeof this.sessionId !== "string" || !invalidTypes.includes(data.type) || !data.url || typeof data.url !== "string") {
399 | resolve({success: false, code: 500, errormessage: "Solve function received invalid parameters, please contact a dev."})
400 | return;
401 | }
402 |
403 | if (typeof data.userAgent !== "string") {
404 | data.userAgent = this.originalUserAgent;
405 | }
406 |
407 | if (typeof data.proxy === "object" && typeof data.proxy.scheme === "string" && typeof data.proxy.host === "string" && typeof data.proxy.port === "number" && data.proxy.port > 0) {
408 | const payload = { proxy: data.proxy, userAgent: data.userAgent };
409 | await this.client.Runtime.evaluate({
410 | expression: `consoleMessageHandler(${JSON.stringify({ type: "modifyData", data: payload })});`
411 | }, this.extensionSessionId);
412 |
413 | await delay(100);
414 | } else if (data.proxy === undefined) {
415 | await this.client.Runtime.evaluate({
416 | expression: `consoleMessageHandler(${JSON.stringify({ type: "modifyData", data: { userAgent: data.userAgent } })});`
417 | }, this.extensionSessionId);
418 |
419 | await delay(100);
420 | } else {
421 | resolve({
422 | success: false,
423 | code: 500,
424 | errormessage: "Proxy entered is invalid, please check your parameters and try again."
425 | });
426 | return;
427 | }
428 |
429 | this.resolve = resolve; this.data = data; this.proxyUrl = data.proxy?.scheme && data.proxy?.host && data.proxy?.port ? `${data.proxy.scheme}://${data.proxy.username && data.proxy.password ? `${data.proxy.username}:${data.proxy.password}@` : ''}${data.proxy.host}:${data.proxy.port}` : undefined;
430 |
431 | await this.client.Network.clearBrowserCookies(this.sessionId);
432 | await this.client.Emulation.setUserAgentOverride({ userAgent: data.userAgent }, this.sessionId )
433 | await this.client.Network.enable(this.sessionId);
434 | /*await this.client.Network.setExtraHTTPHeaders({
435 | headers: {
436 | 'X-User-Agent': this.data.userAgent,
437 | 'X-Proxy-Agent': this.proxyUrl
438 | }
439 | }, sessionId);*/
440 |
441 | if (data.type === "V3" || data.type === "IUAM") {
442 | if (this.proxyOverride !== true && (!data.proxy || !data.proxy.scheme || !data.proxy.host || typeof data.proxy.port !== "number")) {
443 | resolve({
444 | success: false,
445 | code: 500,
446 | errormessage: "A Proxy is required for this type of solve, please enter a proxy into your request and try again."
447 | });
448 | return;
449 | }
450 |
451 | // Construct headers if user agent is provided
452 | const headers = data.userAgent ? ['-H', `User-Agent: ${data.userAgent}`] : undefined;
453 |
454 | // Perform the HTTP request
455 | let html = await curl(data.url, "GET", this.proxyUrl, headers);
456 |
457 | if (!html.success) {
458 | resolve({
459 | success: false,
460 | code: html.code,
461 | cerror: html.err ? html.err : undefined,
462 | error: html.error ? html.error : undefined,
463 | errormessage: html.errormessage ? html.errormessage : "Unknown error occurred, please contact a dev."
464 | });
465 | return;
466 | }
467 |
468 | if (html.redirected) {
469 | resolve({
470 | success: false,
471 | code: 400,
472 | cerror: html.err ? html.err : undefined,
473 | errormessage: "Given URL leads to a redirect, please enter a URL that returns a cloudflare challenge."
474 | });
475 | return;
476 | }
477 |
478 | if (typeof html !== "object" || typeof html.response !== "string" || html.status !== 403 || !html.response.includes('')) {
479 | resolve({
480 | success: false,
481 | code: 400,
482 | cerror: html.err ? html.err : undefined,
483 | errormessage: "Failed to find IUAM challenge. Check the URL or proxy."
484 | });
485 | return;
486 | }
487 |
488 | await this.client.Page.navigate({ url: data.url }, this.sessionId)
489 | }
490 |
491 | if (data.type === "Turnstile") {
492 | await this.client.Page.navigate({ url: data.url }, this.sessionId)
493 | }
494 |
495 | if (data.type === "Invisible") {
496 | if (this.proxyOverride !== true && (!data.proxy || !data.proxy.scheme || !data.proxy.host || typeof data.proxy.port !== "number")) {
497 | resolve({
498 | success: false,
499 | code: 500,
500 | errormessage: "A Proxy is required for this type of solve, please enter a proxy into your request and try again."
501 | });
502 | return;
503 | }
504 |
505 | await this.client.Page.navigate({ url: data.url }, this.sessionId)
506 | }
507 |
508 | if (data.type === "RecaptchaInvisible") {
509 | if (typeof data.action !== "string") {
510 | resolve({
511 | success: false,
512 | code: 400,
513 | errormessage: "An action parameter is required for this type of solve, please enter an action into your request and try again."
514 | });
515 | return;
516 | }
517 |
518 | await this.client.Page.navigate({ url: data.url }, this.sessionId)
519 | }
520 | } catch (error) {
521 | resolve({
522 | success: false,
523 | code: 500,
524 | errormessage: "An error occurred on our side. Please check your request or try again later.",
525 | error
526 | });
527 | return;
528 | }
529 | })
530 | }
531 | }
532 |
533 | export default Solve
534 |
--------------------------------------------------------------------------------
/lib/SolveIUAM.js:
--------------------------------------------------------------------------------
1 | import delay from "./delay.js";
2 | import { EventEmitter } from 'events';
3 | import CDP from "chrome-remote-interface";
4 |
5 | const blockResourceTypes = ["Image", "Font", "Stylesheet", "Other", "Media"];
6 |
7 | /**
8 | * @param {CDP.Client} client
9 | */
10 | const waitForLoading = (client, requestId, sessionId) => {
11 | return new Promise((resolve) => {
12 | client.Network.loadingFinished(({ requestId: finishedRequestId }) => {
13 | if (finishedRequestId === requestId) {
14 | resolve();
15 | }
16 | }, sessionId);
17 | });
18 | };
19 |
20 | /**
21 | * @param {CDP.Client} client
22 | */
23 | async function Solver(client, eventEmitter, sessionId) {
24 | let keepRunning = true;
25 |
26 | eventEmitter.once('stop', () => {
27 | keepRunning = false;
28 | });
29 |
30 | while (keepRunning) {
31 | try {
32 | await delay(1000);
33 |
34 | const { nodes } = await client.DOM.getFlattenedDocument(
35 | {
36 | depth: -1,
37 | pierce: true,
38 | },
39 | sessionId
40 | );
41 |
42 | const turnstileNode = nodes.find(
43 | (node) =>
44 | node.nodeName === "IFRAME" &&
45 | node.attributes?.includes("Widget containing a Cloudflare security challenge")
46 | );
47 |
48 | if (!turnstileNode) {
49 | continue;
50 | }
51 |
52 | // Try to get the box model (dimensions) of the node
53 | const location = await client.DOM.getBoxModel(
54 | { nodeId: turnstileNode.nodeId },
55 | sessionId
56 | );
57 | const [x1, y1, x2, y2, x3, y3, x4, y4] = location.model.content;
58 |
59 | // Calculate center
60 | const x = (x1 + x3) / 2;
61 | const y = (y1 + y3) / 2;
62 |
63 | await delay(1000);
64 |
65 | await client.Input.dispatchMouseEvent(
66 | {
67 | type: 'mouseMoved',
68 | x,
69 | y,
70 | },
71 | sessionId
72 | );
73 |
74 | // Press the left mouse button
75 | await client.Input.dispatchMouseEvent(
76 | {
77 | type: 'mousePressed',
78 | x,
79 | y,
80 | button: 'left',
81 | clickCount: 1,
82 | },
83 | sessionId
84 | );
85 |
86 | // Release the left mouse button
87 | await client.Input.dispatchMouseEvent(
88 | {
89 | type: 'mouseReleased',
90 | x,
91 | y,
92 | button: 'left',
93 | clickCount: 1,
94 | },
95 | sessionId
96 | );
97 | } catch (error) {
98 | // Resolve errors silently
99 | }
100 | }
101 | }
102 |
103 | /**
104 | * @param {CDP.Client} client
105 | */
106 | async function SolveIUAM(client, url, html, proxy) {
107 | return new Promise(async (resolve, reject) => {
108 | let sessionId;
109 | const eventEmitter = new EventEmitter();
110 | const timeout = setTimeout(async () => {
111 | try {
112 | await client.DOM.disable(sessionId);
113 | await client.Page.disable(sessionId);
114 | await client.Network.disable(sessionId);
115 | await client.Page.navigate({ url: html }, sessionId);
116 | resolve({ success: false, code: 408, errormessage: "Request timed out." });
117 | } catch (error) {
118 | resolve({ success: false, code: 408, errormessage: "Request timed out." });
119 | }
120 | }, 30000); // 30-second timeout
121 |
122 | try {
123 | const targets = (await client.Target.getTargets()).targetInfos;
124 | const target = targets.find((target) => target.type === "page");
125 | const targetId = target.targetId;
126 | sessionId = (await client.Target.attachToTarget({ targetId, flatten: true })).sessionId;
127 |
128 | await client.DOM.enable(sessionId);
129 | await client.Page.enable(sessionId);
130 | await client.Network.enable(undefined, sessionId);
131 |
132 | await client.Network.setRequestInterception({
133 | patterns: [{ urlPattern: "*" }],
134 | }, sessionId);
135 |
136 | client.Network.requestIntercepted(async (listener) => {
137 | try {
138 | if (listener.authChallenge) {
139 | if (!proxy.username || !proxy.password) {
140 | clearTimeout(timeout);
141 | resolve({
142 | success: false,
143 | code: 500,
144 | errormessage: "Proxy Provided requires a Username & Password, request is missing one or more of these parameters."
145 | });
146 | return;
147 | }
148 | await client.Network.continueInterceptedRequest({
149 | interceptionId: listener.interceptionId,
150 | authChallengeResponse: {
151 | response: "ProvideCredentials",
152 | username: proxy.username,
153 | password: proxy.password,
154 | },
155 | }, sessionId);
156 | } else if (blockResourceTypes.includes(listener.resourceType)) {
157 | await client.Network.continueInterceptedRequest({
158 | interceptionId: listener.interceptionId,
159 | rawResponse: Buffer.from('HTTP/2 404 CloudFreed Stopped media\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n\r\n').toString('base64')
160 | }, sessionId);
161 | } else {
162 | await client.Network.continueInterceptedRequest({
163 | interceptionId: listener.interceptionId,
164 | }, sessionId);
165 |
166 | if (listener.request.url === url && listener.request.method === "POST") {
167 | await waitForLoading(client, listener.requestId, sessionId);
168 |
169 | let cookies = await client.Network.getCookies(undefined, sessionId);
170 | let cookie = cookies.cookies.find(cookie => cookie.name === 'cf_clearance');
171 |
172 | if (cookie) {
173 | await client.Runtime.evaluate({ expression: "document.write()" }, sessionId);
174 |
175 | await client.DOM.disable(sessionId);
176 | await client.Page.disable(sessionId);
177 | await client.Network.disable(sessionId);
178 | eventEmitter.emit('stop');
179 |
180 | await client.Page.navigate({ url: html }, sessionId);
181 |
182 | clearTimeout(timeout);
183 | resolve({ success: true, code: 200, cfClearance: cookie });
184 | }
185 | }
186 | }
187 | } catch (error) {
188 | // Resolve errors silently
189 | }
190 | });
191 |
192 | await client.Page.navigate({ url }, sessionId);
193 | await client.Emulation.setFocusEmulationEnabled({ enabled: true }, sessionId);
194 |
195 | Solver(client, eventEmitter, sessionId);
196 | } catch (error) {
197 | try {
198 | if (sessionId) {
199 | await client.DOM.disable(sessionId);
200 | await client.Page.disable(sessionId);
201 | await client.Network.disable(sessionId);
202 | await client.Page.navigate({ url: html }, sessionId);
203 | }
204 |
205 | clearTimeout(timeout);
206 | resolve({
207 | success: false,
208 | code: 500,
209 | error,
210 | errormessage: "An error occurred on our side. Please check your request or try again later."
211 | });
212 | } catch (error) {
213 | clearTimeout(timeout);
214 | resolve({
215 | success: false,
216 | code: 500,
217 | error,
218 | errormessage: "An error occurred on our side. Please check your request or try again later."
219 | });
220 | }
221 | }
222 | });
223 | }
224 |
225 | export default SolveIUAM;
226 |
--------------------------------------------------------------------------------
/lib/SolveTurnstile.js:
--------------------------------------------------------------------------------
1 | import delay from "./delay.js";
2 | import { EventEmitter } from 'events';
3 | import CDP from "chrome-remote-interface";
4 |
5 | const blockResourceTypes = ["Image", "Font", "Stylesheet", "Other", "Media"];
6 |
7 | function generateTurnstileHTML(sitekey) {
8 | return `
9 |
10 |
11 |
12 |
13 |
14 | CloudFreed
15 |
16 |
32 |
33 |
34 |
37 |
38 |
39 |
40 | `;
41 | }
42 |
43 | /**
44 | * @param {CDP.Client} client
45 | */
46 | async function Solver(client, eventEmitter, sessionId) {
47 | let keepRunning = true;
48 |
49 | eventEmitter.once('stop', () => {
50 | keepRunning = false;
51 | });
52 |
53 | while (keepRunning) {
54 | try {
55 | await delay(1000);
56 |
57 | const { nodes } = await client.DOM.getFlattenedDocument(
58 | {
59 | depth: -1,
60 | pierce: true,
61 | },
62 | sessionId
63 | );
64 |
65 | const turnstileNode = nodes.find(
66 | (node) =>
67 | node.nodeName === "IFRAME" &&
68 | node.attributes?.includes("Widget containing a Cloudflare security challenge")
69 | );
70 |
71 | if (!turnstileNode) {
72 | continue;
73 | }
74 |
75 | // Try to get the box model (dimensions) of the node
76 | const location = await client.DOM.getBoxModel(
77 | { nodeId: turnstileNode.nodeId },
78 | sessionId
79 | );
80 | const [x1, y1, x2, y2, x3, y3, x4, y4] = location.model.content;
81 |
82 | // Calculate center
83 | const x = (x1 + x3) / 2;
84 | const y = (y1 + y3) / 2;
85 |
86 | await delay(1000);
87 |
88 | await client.Input.dispatchMouseEvent(
89 | {
90 | type: 'mouseMoved',
91 | x,
92 | y,
93 | },
94 | sessionId
95 | );
96 |
97 | // Press the left mouse button
98 | await client.Input.dispatchMouseEvent(
99 | {
100 | type: 'mousePressed',
101 | x,
102 | y,
103 | button: 'left',
104 | clickCount: 1,
105 | },
106 | sessionId
107 | );
108 |
109 | // Release the left mouse button
110 | await client.Input.dispatchMouseEvent(
111 | {
112 | type: 'mouseReleased',
113 | x,
114 | y,
115 | button: 'left',
116 | clickCount: 1,
117 | },
118 | sessionId
119 | );
120 | } catch (error) {
121 | // Handle errors silently
122 | }
123 | }
124 | }
125 |
126 | /**
127 | * @param {CDP.Client} client
128 | */
129 | async function SolveTurnstile(client, url, sitekey, html, proxy) {
130 | return new Promise(async (resolve, reject) => {
131 | let sessionId;
132 | const eventEmitter = new EventEmitter();
133 | const timeout = setTimeout(async () => {
134 | try {
135 | await client.DOM.disable(sessionId);
136 | await client.Page.disable(sessionId);
137 | await client.Network.disable(sessionId);
138 | await client.Page.navigate({ url: html }, sessionId);
139 | resolve({ success: false, code: 408, errormessage: "Request timed out." });
140 | } catch (error) {
141 | resolve({ success: false, code: 408, errormessage: "Request timed out." });
142 | }
143 | }, 30000); // 30-second timeout
144 |
145 | try {
146 | const targets = (await client.Target.getTargets()).targetInfos;
147 | const target = targets.find((target) => target.type === "page");
148 | const targetId = target.targetId;
149 | sessionId = (await client.Target.attachToTarget({ targetId, flatten: true })).sessionId;
150 |
151 | await client.DOM.enable(sessionId);
152 | await client.Page.enable(sessionId);
153 | await client.Network.enable(sessionId);
154 |
155 | await client.Network.setRequestInterception({
156 | patterns: [{ urlPattern: "*" }],
157 | }, sessionId);
158 |
159 | client.Network.requestIntercepted(async (listener) => {
160 | try {
161 | if (listener.authChallenge) {
162 | await client.Network.continueInterceptedRequest({
163 | interceptionId: listener.interceptionId,
164 | authChallengeResponse: {
165 | response: "ProvideCredentials",
166 | username: proxy.username,
167 | password: proxy.password,
168 | },
169 | }, sessionId);
170 | } else if (blockResourceTypes.includes(listener.resourceType)) {
171 | await client.Network.continueInterceptedRequest({
172 | interceptionId: listener.interceptionId,
173 | rawResponse: Buffer.from('HTTP/2 404 CloudFreed Stopped media\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n\r\n').toString('base64')
174 | }, sessionId);
175 | } else if (listener.request.url.includes(url)) {
176 | await client.Network.continueInterceptedRequest({
177 | interceptionId: listener.interceptionId,
178 | rawResponse: Buffer.from('HTTP/2 200 OK\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n' + generateTurnstileHTML(sitekey)).toString('base64')
179 | }, sessionId);
180 | } else {
181 | await client.Network.continueInterceptedRequest({
182 | interceptionId: listener.interceptionId,
183 | }, sessionId);
184 | }
185 | } catch (error) {
186 | // Resolve errors silently
187 | }
188 | });
189 |
190 | await client.Page.navigate({ url }, sessionId);
191 | Solver(client, eventEmitter, sessionId);
192 |
193 | async function waitForTurnstileValue() {
194 | while (true) {
195 | try {
196 | await delay(1000);
197 |
198 | // Get the document's flattened node tree
199 | const { root: { nodeId: documentNodeId } } = await client.DOM.getDocument({}, sessionId);
200 |
201 | // Query for the specific input element
202 | const { nodeId } = await client.DOM.querySelector({
203 | nodeId: documentNodeId,
204 | selector: '#cf-turnstile > div > input'
205 | }, sessionId);
206 |
207 | if (nodeId) {
208 | // Get the input attributes
209 | const { attributes } = await client.DOM.getAttributes({ nodeId }, sessionId);
210 |
211 | // Find the index of the 'value' attribute
212 | const valueIndex = attributes.indexOf('value');
213 | if (valueIndex !== -1) {
214 | // The value is at the index right after 'value'
215 | const inputValue = attributes[valueIndex + 1];
216 | if (inputValue) {
217 | return inputValue;
218 | }
219 | }
220 | }
221 | } catch (error) {
222 | // Resolve errors silently
223 | }
224 | }
225 | }
226 |
227 | const response = await waitForTurnstileValue();
228 |
229 | await client.DOM.disable(sessionId);
230 | await client.Page.disable(sessionId);
231 | await client.Network.disable(sessionId);
232 | eventEmitter.emit('stop');
233 |
234 | await client.Page.navigate({ url: html }, sessionId);
235 |
236 | clearTimeout(timeout);
237 | resolve({ success: true, code: 200, response });
238 | } catch (error) {
239 | try {
240 | if (sessionId) {
241 | await client.DOM.disable(sessionId);
242 | await client.Page.disable(sessionId);
243 | await client.Network.disable(sessionId);
244 | await client.Page.navigate({ url: html }, sessionId);
245 | }
246 |
247 | clearTimeout(timeout);
248 | resolve({
249 | success: false,
250 | code: 500,
251 | error,
252 | errormessage: "An error occurred on our side. Please check your request or try again later."
253 | });
254 | } catch (error) {
255 | clearTimeout(timeout);
256 | resolve({
257 | success: false,
258 | code: 500,
259 | error,
260 | errormessage: "An error occurred on our side. Please check your request or try again later."
261 | });
262 | }
263 | }
264 | });
265 | }
266 |
267 | export default SolveTurnstile;
268 |
--------------------------------------------------------------------------------
/lib/SolveV3.js:
--------------------------------------------------------------------------------
1 | import delay from "./delay.js";
2 | import CDP from "chrome-remote-interface";
3 |
4 | const blockResourceTypes = ["Image", "Font", "Stylesheet", "Other", "Media"];
5 | const scriptRegex = /window\.__CF\$cv\$params\s*=\s*\{r:'(.+?)',t:'(.+?)'\};/;
6 |
7 | /**
8 | * @param {CDP.Client} client
9 | */
10 | const waitForLoading = (client, requestId, sessionId) => {
11 | return new Promise((resolve) => {
12 | client.Network.loadingFinished(({ requestId: finishedRequestId }) => {
13 | if (finishedRequestId === requestId) {
14 | resolve();
15 | }
16 | }, sessionId);
17 | });
18 | };
19 |
20 | function generateTurnstileHTML(r, t) {
21 | return `
22 |
23 |
24 |
25 |
26 |
27 | CloudFreed
28 |
29 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
54 |
55 |
56 |
57 |
58 |
59 | `;
60 | }
61 |
62 | /**
63 | * @param {CDP.Client} client
64 | */
65 | async function SolveV3(client, url, html, proxy) {
66 | return new Promise(async (resolve, reject) => {
67 | let sessionId;
68 | const timeout = setTimeout(async () => {
69 | try {
70 | await client.DOM.disable(sessionId);
71 | await client.Page.disable(sessionId);
72 | await client.Network.disable(sessionId);
73 | await client.Page.navigate({ url: html }, sessionId);
74 | resolve({ success: false, code: 408, errormessage: "Request timed out." });
75 | } catch (error) {
76 | resolve({ success: false, code: 408, errormessage: "Request timed out." });
77 | }
78 | }, 30000); // 30-second timeout
79 |
80 | try {
81 | const targets = (await client.Target.getTargets()).targetInfos;
82 | const target = targets.find((target) => target.type === "page");
83 | const targetId = target.targetId;
84 | sessionId = (await client.Target.attachToTarget({ targetId, flatten: true })).sessionId;
85 |
86 | await client.DOM.enable(sessionId);
87 | await client.Page.enable(sessionId);
88 | await client.Network.enable(undefined, sessionId);
89 |
90 | await client.Network.setRequestInterception({
91 | patterns: [{ urlPattern: "*" }, { urlPattern: url, interceptionStage: "HeadersReceived" }],
92 | }, sessionId);
93 |
94 | client.Network.requestIntercepted(async (listener) => {
95 | try {
96 | if (listener.authChallenge) {
97 | if (!proxy.username || !proxy.password) {
98 | await client.DOM.disable(sessionId);
99 | await client.Page.disable(sessionId);
100 | await client.Network.disable(sessionId);
101 | await client.Page.navigate({ url: html }, sessionId);
102 |
103 | clearTimeout(timeout);
104 | resolve({
105 | success: false,
106 | code: 500,
107 | errormessage: "Proxy Provided requires a Username & Password, request is missing one or more of these parameters."
108 | });
109 | return;
110 | }
111 | await client.Network.continueInterceptedRequest({
112 | interceptionId: listener.interceptionId,
113 | authChallengeResponse: {
114 | response: "ProvideCredentials",
115 | username: proxy.username,
116 | password: proxy.password,
117 | },
118 | }, sessionId);
119 | } else if (blockResourceTypes.includes(listener.resourceType)) {
120 | await client.Network.continueInterceptedRequest({
121 | interceptionId: listener.interceptionId,
122 | rawResponse: Buffer.from('HTTP/2 404 CloudFreed Stopped media\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n\r\n').toString('base64')
123 | }, sessionId);
124 | } else if (listener.request.url === url && listener.request.method === "GET" && listener.responseStatusCode) {
125 | let body = await client.Network.getResponseBodyForInterception({ interceptionId: listener.interceptionId }, sessionId);
126 |
127 | if (body.base64Encoded) {
128 | body = Buffer.from(body.body, 'base64').toString('utf-8');
129 | }
130 |
131 | // Search for the script
132 | const script = body.match(scriptRegex);
133 |
134 | if (script && script[1] && script[2]) {
135 | await client.Network.continueInterceptedRequest({
136 | interceptionId: listener.interceptionId,
137 | rawResponse: Buffer.from('HTTP/2 200 OK\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n' + generateTurnstileHTML(script[1], script[2])).toString('base64')
138 | }, sessionId);
139 | } else {
140 | await client.Network.continueInterceptedRequest({
141 | interceptionId: listener.interceptionId,
142 | rawResponse: Buffer.from('HTTP/2 401 NO CHALLENGE\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n').toString("base64")
143 | }, sessionId);
144 |
145 | await client.DOM.disable(sessionId);
146 | await client.Page.disable(sessionId);
147 | await client.Network.disable(sessionId);
148 | await client.Page.navigate({ url: html }, sessionId);
149 |
150 | clearTimeout(timeout);
151 | resolve({
152 | success: false,
153 | code: 500,
154 | errormessage: "Failed to find V3 challenge."
155 | });
156 | }
157 | } else {
158 | await client.Network.continueInterceptedRequest({
159 | interceptionId: listener.interceptionId,
160 | }, sessionId);
161 |
162 | if (listener.request.url.includes('/cdn-cgi/challenge-platform/h/b/jsd/') && !listener.responseStatusCode) {
163 | await waitForLoading(client, listener.requestId, sessionId);
164 |
165 | let cookies = await client.Network.getCookies(undefined, sessionId);
166 | let cookie = cookies.cookies.find(cookie => cookie.name === 'cf_clearance');
167 |
168 | if (cookie) {
169 | await client.DOM.disable(sessionId);
170 | await client.Page.disable(sessionId);
171 | await client.Network.disable(sessionId);
172 | await client.Page.navigate({ url: html }, sessionId);
173 |
174 | clearTimeout(timeout);
175 | resolve({ success: true, code: 200, cfClearance: cookie });
176 | }
177 | }
178 | }
179 | } catch (error) {
180 | console.error(error);
181 | // Resolve errors silently
182 | }
183 | });
184 |
185 | await client.Page.navigate({ url }, sessionId);
186 | await client.Emulation.setFocusEmulationEnabled({ enabled: true }, sessionId);
187 | } catch (error) {
188 | try {
189 | if (sessionId) {
190 | await client.DOM.disable(sessionId);
191 | await client.Page.disable(sessionId);
192 | await client.Network.disable(sessionId);
193 | await client.Page.navigate({ url: html }, sessionId);
194 | }
195 |
196 | clearTimeout(timeout);
197 | resolve({
198 | success: false,
199 | code: 500,
200 | error,
201 | errormessage: "An error occurred on our side. Please check your request or try again later."
202 | });
203 | } catch (error) {
204 | clearTimeout(timeout);
205 | resolve({
206 | success: false,
207 | code: 500,
208 | error,
209 | errormessage: "An error occurred on our side. Please check your request or try again later."
210 | });
211 | }
212 | }
213 | });
214 | }
215 |
216 | export default SolveV3;
217 |
--------------------------------------------------------------------------------
/lib/StatusText.js:
--------------------------------------------------------------------------------
1 | function StatusText() {
2 | const ST = {
3 | "100": "Continue",
4 | "101": "Switching Protocols",
5 | "102": "Processing",
6 | "103": "Early Hints",
7 | "200": "OK",
8 | "201": "Created",
9 | "202": "Accepted",
10 | "203": "Non-Authoritative Information",
11 | "204": "No Content",
12 | "205": "Reset Content",
13 | "206": "Partial Content",
14 | "207": "Multi-Status",
15 | "208": "Already Reported",
16 | "226": "IM Used",
17 | "300": "Multiple Choices",
18 | "301": "Moved Permanently",
19 | "302": "Found",
20 | "303": "See Other",
21 | "304": "Not Modified",
22 | "305": "Use Proxy",
23 | "307": "Temporary Redirect",
24 | "308": "Permanent Redirect",
25 | "400": "Bad Request",
26 | "401": "Unauthorized",
27 | "402": "Payment Required",
28 | "403": "Forbidden",
29 | "404": "Not Found",
30 | "405": "Method Not Allowed",
31 | "406": "Not Acceptable",
32 | "407": "Proxy Authentication Required",
33 | "408": "Request Timeout",
34 | "409": "Conflict",
35 | "410": "Gone",
36 | "411": "Length Required",
37 | "412": "Precondition Failed",
38 | "413": "Payload Too Large",
39 | "414": "URI Too Long",
40 | "415": "Unsupported Media Type",
41 | "416": "Range Not Satisfiable",
42 | "417": "Expectation Failed",
43 | "418": "I'm a teapot",
44 | "421": "Misdirected Request",
45 | "422": "Unprocessable Entity",
46 | "423": "Locked",
47 | "424": "Failed Dependency",
48 | "425": "Too Early",
49 | "426": "Upgrade Required",
50 | "428": "Precondition Required",
51 | "429": "Too Many Requests",
52 | "431": "Request Header Fields Too Large",
53 | "451": "Unavailable For Legal Reasons",
54 | "500": "Internal Server Error",
55 | "501": "Not Implemented",
56 | "502": "Bad Gateway",
57 | "503": "Service Unavailable",
58 | "504": "Gateway Timeout",
59 | "505": "HTTP Version Not Supported",
60 | "506": "Variant Also Negotiates",
61 | "507": "Insufficient Storage",
62 | "508": "Loop Detected",
63 | "510": "Not Extended",
64 | "511": "Network Authentication Required"
65 | };
66 | return ST
67 | }
68 |
69 | export default StatusText
--------------------------------------------------------------------------------
/lib/ValidateURL.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Validates and formats the given URL by ensuring it has a protocol, removing spaces,
3 | * and ensuring it ends with a forward slash.
4 | *
5 | * @param {String} url - The URL to validate and format.
6 | * @returns {String} - The formatted URL.
7 | */
8 | function validateURL(url) {
9 | if (typeof url === "string") {
10 | // Trim any leading/trailing whitespace
11 | url = url.trim();
12 |
13 | // Ensure the URL has a protocol; if not, prepend "https://"
14 | const hasProtocol = /^https?:\/\//i.test(url);
15 | if (!hasProtocol) {
16 | url = "https://" + url;
17 | }
18 |
19 | // Remove all spaces from the URL
20 | url = url.replace(/ /g, "");
21 |
22 | // Ensure the URL ends with a single forward slash
23 | if (!url.endsWith("/")) {
24 | url += "/";
25 | }
26 |
27 | return url;
28 | }
29 | }
30 |
31 | export default validateURL;
32 |
--------------------------------------------------------------------------------
/lib/curl.js:
--------------------------------------------------------------------------------
1 | import { accessFile } from "./fs.js";
2 |
3 | import { spawn } from 'child_process';
4 | import path from 'path';
5 | import { fileURLToPath } from 'url';
6 |
7 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
8 | const curlPath = path.join(__dirname, 'curl', 'curl.exe');
9 | const regex = /301|302|303|307/;
10 | const defaultArgs = [
11 | '-w', '\n%{http_code}|%{url_effective}',
12 | '-k',
13 | '-i',
14 | '-H', 'Upgrade-Insecure-Requests: 1',
15 | '-H', 'Cache-Control: max-age=0',
16 | '-H', 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
17 | '-H', 'Accept-Encoding: gzip, deflate, br, zstd',
18 | '-H', 'Accept-Language: en-US,en;q=0.9',
19 | '-H', 'Priority: u=0, i',
20 | '--ciphers', 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:TLS_RSA_WITH_AES_128_GCM_SHA256:TLS_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_128_CBC_SHA:TLS_RSA_WITH_AES_256_CBC_SHA',
21 | '--compressed',
22 | ]
23 |
24 | await accessFile(curlPath);
25 |
26 | /**
27 | *
28 | * @param {string} url
29 | * @param {string} mode
30 | * @param {string} proxy
31 | * @param {string[]} params
32 | * @returns {Promise<{ success:boolean, code:number, error:object|undefined, errormessage:string|undefined, err:string|undefined, args:string[]|undefined, redirected:boolean|undefined, headers:string[]|undefined, response:string|undefined, status:number|undefined, url:string|undefined }>}
33 | */
34 | async function curl(url, mode, proxy, params) {
35 | return new Promise(async (resolve) => {
36 | try {
37 | if (typeof mode !== "string") {
38 | return resolve({ success: false, code: 400, errormessage: "Invalid mode entered, please check your parameters." });
39 | }
40 |
41 | let args = [...defaultArgs];
42 |
43 | if (typeof params === "object") {
44 | if (!params.find(param => param.startsWith("User-Agent:"))) {
45 | args.push('-H', 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36')
46 | }
47 |
48 | args.push(...params)
49 | } else {
50 | args.push('-H', 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36')
51 | }
52 |
53 | if (typeof proxy === "string" && (proxy.startsWith("http://") || proxy.startsWith("https://") || proxy.startsWith("socks4://") || proxy.startsWith("socks5://"))) {
54 | args.push('--proxy', proxy);
55 | } else if (proxy !== undefined) {
56 | return resolve({ success: false, code: 400, errormessage: "Invalid proxy entered, please check your parameters." });
57 | }
58 |
59 | if (typeof url === "string") {
60 | args.push(mode, url);
61 | } else {
62 | return resolve({ success: false, code: 500, errormessage: "Invalid URL entered, please check your parameters." });
63 | }
64 |
65 | const curl = spawn(path.join(__dirname, 'curl', 'curl.exe'), args);
66 |
67 | let out = '';
68 | let err = '';
69 |
70 | // Capture stdout and stderr streams
71 | curl.stdout.on('data', (data) => {
72 | try {
73 | out += data.toString();
74 | } catch {}
75 | });
76 |
77 | curl.stderr.on('data', (data) => {
78 | try {
79 | err += data.toString();
80 | } catch {}
81 | });
82 |
83 | // Handle the close event
84 | curl.on('close', (code) => {
85 | try {
86 | if (code !== 0) {
87 | return resolve({ success: false, code: 500, err, errormessage: "Error occurred when requesting from URL, please check URL/proxy." });
88 | }
89 |
90 | let outs = out.split('\r\n\r\n')
91 |
92 | if (typeof proxy === "string") {
93 | outs.shift()
94 | }
95 |
96 | let headers = outs.shift()
97 | let body = outs.join('\r\n\r\n')
98 |
99 | headers = headers.trim().split('\r\n').splice(1)
100 |
101 | let headersObject = {};
102 |
103 | headers.forEach(header => {
104 | let [name, ...value] = header.split(':');
105 | headersObject[name.trim()] = value.join(':').trim();
106 | });
107 |
108 | const lines = body.trim().split('\n');
109 | const data = lines.pop()
110 | const [responseStatusCode, responseUrl] = [parseInt(data.split('|')[0], 10), data.split('|')[1]]; // Remove and parse the last line as the status code
111 | const responseBodyContent = lines.join('\n'); // Join the remaining lines into a string
112 |
113 | let redirected = regex.test(responseStatusCode)
114 |
115 | return resolve({ success: true, code: 200, err, args, redirected, headers: headersObject, response: responseBodyContent, status: responseStatusCode, url: responseUrl });
116 | } catch (error) {
117 | return resolve({ success: false, code: 500, err, error, errormessage: "Error occurred while resolving curl." });
118 | }
119 | });
120 |
121 | // Capture any possible errors that happen during spawning or execution
122 | curl.on('error', (error) => {
123 | return resolve({ success: false, code: 500, error, errormessage: "Error occurred while running curl." });
124 | });
125 | } catch (error) {
126 | return resolve({ success: false, code: 500, error, errormessage: "Error occurred while starting curl." });
127 | }
128 | });
129 | }
130 |
131 | export default curl
--------------------------------------------------------------------------------
/lib/curl/curl.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akmal-abar/CloudFreed-CloudFlare-solver-bypass/568fe1ef56ddad4b0249ac0e0112d5b4dbba0b07/lib/curl/curl.exe
--------------------------------------------------------------------------------
/lib/delay.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Introduce a delay.
3 | * @param {number} milliseconds - The duration of the delay in milliseconds.
4 | * @returns {Promise} - A promise that resolves after the delay.
5 | */
6 | const delay = async (milliseconds) => await new Promise(resolve => setTimeout(resolve, milliseconds));
7 |
8 | export default delay
--------------------------------------------------------------------------------
/lib/fs.js:
--------------------------------------------------------------------------------
1 | import fs from "fs/promises";
2 |
3 | async function readFile(path) {
4 | try {
5 | await fs.access(path);
6 |
7 | // Read the file
8 | const data = await fs.readFile(path, "utf-8");
9 | return data;
10 | } catch (err) {
11 | // Handle specific errors
12 | if (err.code === 'ENOENT') {
13 | throw new Error(`File not found: ${path}`);
14 | } else {
15 | throw new Error(`Unable to read file: ${err.message}`);
16 | }
17 | }
18 | }
19 |
20 | async function writeFile(path, datuh) {
21 | try {
22 | await fs.access(path);
23 |
24 | // Read the file
25 | const data = await fs.writeFile(path, datuh, "utf-8")
26 | return data;
27 | } catch (err) {
28 | // Handle specific errors
29 | if (err.code === 'ENOENT') {
30 | throw new Error(`File not found: ${path}`);
31 | } else {
32 | throw new Error(`Unable to read file: ${err.message}`);
33 | }
34 | }
35 | }
36 |
37 | async function accessFile(path) {
38 | try {
39 | await fs.access(path);
40 |
41 | return true;
42 | } catch (err) {
43 | // Handle specific errors
44 | if (err.code === 'ENOENT') {
45 | throw new Error(`File not found: ${path}`);
46 | } else {
47 | throw new Error(`Unable to read file: ${err.message}`);
48 | }
49 | }
50 | }
51 |
52 | export { readFile, writeFile, accessFile }
--------------------------------------------------------------------------------
/lib/proxyManager/background.js:
--------------------------------------------------------------------------------
1 | const ALL_RESOURCE_TYPES = [
2 | 'main_frame',
3 | 'sub_frame',
4 | 'stylesheet',
5 | 'script',
6 | 'image',
7 | 'font',
8 | 'object',
9 | 'xmlhttprequest',
10 | 'ping',
11 | 'csp_report',
12 | 'media',
13 | 'websocket',
14 | 'webtransport',
15 | 'webbundle',
16 | 'other',
17 | ];
18 |
19 | async function setUserAgentOverride(userAgent) {
20 | chrome.declarativeNetRequest.updateDynamicRules({
21 | removeRuleIds: [1], // Remove any existing rule with ID 1
22 | addRules: [
23 | {
24 | id: 1,
25 | priority: 1,
26 | action: {
27 | type: "modifyHeaders",
28 | requestHeaders: [
29 | {
30 | header: "User-Agent",
31 | operation: "set",
32 | value: userAgent
33 | }
34 | ]
35 | },
36 | condition: {
37 | resourceTypes: ALL_RESOURCE_TYPES,
38 | urlFilter: "*"
39 | }
40 | }
41 | ]
42 | });
43 | };
44 |
45 | // Function to update proxy settings
46 | function updateProxy(proxyConfig) {
47 | if (!proxyConfig || typeof proxyConfig.scheme !== "string" || typeof proxyConfig.host !== "string" || typeof proxyConfig.port !== "number") {
48 | console.error('Invalid proxy configuration:', JSON.stringify(proxyConfig));
49 | return;
50 | }
51 |
52 | chrome.proxy.settings.set(
53 | {
54 | value: {
55 | mode: 'fixed_servers',
56 | rules: {
57 | singleProxy: {
58 | scheme: proxyConfig.scheme,
59 | host: proxyConfig.host,
60 | port: parseInt(proxyConfig.port, 10)
61 | }
62 | }
63 | },
64 | scope: 'regular'
65 | },
66 | () => {
67 | console.log('Proxy updated to:', proxyConfig);
68 | }
69 | );
70 | }
71 |
72 | function clearProxy() {
73 | chrome.proxy.settings.clear({}, function() {
74 | if (chrome.runtime.lastError) {
75 | console.error('Error clearing proxy settings:', chrome.runtime.lastError);
76 | } else {
77 | console.log('Proxy settings cleared successfully.');
78 | }
79 | });
80 | }
81 |
82 | self.consoleMessageHandler = (message) => {
83 | console.log("Received message from DevTools console:", JSON.stringify(message));
84 |
85 | if (typeof message === "object" && message.data && message.type === "modifyData") {
86 | if (message.data.userAgent) {
87 | setUserAgentOverride(message.data.userAgent)
88 | }
89 | if (message.data.proxy) {
90 | updateProxy(message.data.proxy)
91 | } else {
92 | clearProxy()
93 | }
94 | }
95 | };
96 |
--------------------------------------------------------------------------------
/lib/proxyManager/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 3,
3 | "name": "Dynamic Proxy Switcher",
4 | "version": "1.0",
5 | "permissions": [
6 | "proxy",
7 | "storage",
8 | "alarms",
9 | "tabs",
10 | "activeTab",
11 | "offscreen",
12 | "scripting",
13 | "declarativeNetRequest"
14 | ],
15 | "background": {
16 | "service_worker": "background.js"
17 | },
18 | "host_permissions": [
19 | "",
20 | "file:///*"
21 | ],
22 | "content_scripts": [
23 | {
24 | "js": [
25 | "./script.js"
26 | ],
27 | "matches": [
28 | ""
29 | ],
30 | "run_at": "document_start",
31 | "all_frames": true,
32 | "world": "MAIN"
33 | }
34 | ],
35 | "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyaj9HL/FT30C8fzyPJ5zrSIqUlUfufpWFpjg6PMkNcaSVVQMls7CJtq6Je493v4kNQRsmDl46tSKOmQ6y/b9OMKqdybuq1vQMxRkyiU3Ib3dCqTIk/oZ7t5wkVIwCONtPf85IQWAGP1NLqw0k51eda7m6QOkW092yPNCR/Y/LA0ZiXYU2qifn1H+f0HXqkyS3go+2TyfmIiiNRVJNUg+8OtcbcRCIcFPi/6l29jzbOgF39tepAss0MBLcdB6TjHWIU6JZfSjZ2xtUXkRmiec0FwiRgVmdIuwZuT2oQlpy6uOCopKZD6sSeMIA6b84/WzDIuZeyzfGvpRzj7OOWJDawIDAQAB"
36 | }
37 |
--------------------------------------------------------------------------------
/lib/proxyManager/script.js:
--------------------------------------------------------------------------------
1 | // content-script.js
2 | (function() {
3 | 'use strict';
4 | Object.defineProperties(window, {
5 | chrome: {
6 | value: undefined,
7 | configurable: false,
8 | enumerable: true,
9 | writable: false
10 | }
11 | })
12 | })();
13 |
14 | function getRandomInt(min, max) {
15 | return Math.floor(Math.random() * (max - min + 1)) + min;
16 | }
17 |
18 | let screenX = getRandomInt(800, 1200);
19 | let screenY = getRandomInt(400, 600);
20 |
21 | Object.defineProperty(MouseEvent.prototype, 'screenX', { value: screenX });
22 |
23 | Object.defineProperty(MouseEvent.prototype, 'screenY', { value: screenY });
--------------------------------------------------------------------------------
/lib/turnstilePatch/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 3,
3 | "name": "Turnstile Patcher",
4 | "version": "1",
5 | "content_scripts": [
6 | {
7 | "js": [
8 | "./script.js"
9 | ],
10 | "matches": [
11 | ""
12 | ],
13 | "run_at": "document_start",
14 | "all_frames": true,
15 | "world": "MAIN"
16 | }
17 | ]
18 | }
--------------------------------------------------------------------------------
/lib/turnstilePatch/script.js:
--------------------------------------------------------------------------------
1 | function getRandomInt(min, max) {
2 | return Math.floor(Math.random() * (max - min + 1)) + min;
3 | }
4 |
5 | let screenX = getRandomInt(800, 1200);
6 | let screenY = getRandomInt(400, 600);
7 |
8 | Object.defineProperty(MouseEvent.prototype, 'screenX', { value: screenX });
9 |
10 | Object.defineProperty(MouseEvent.prototype, 'screenY', { value: screenY });
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cloudfreed",
3 | "version": "3.1.1",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "cloudfreed",
9 | "version": "3.1.1",
10 | "license": "ISC",
11 | "dependencies": {
12 | "axios": "^1.7.7",
13 | "chrome-remote-interface": "^0.33.2",
14 | "fs": "^0.0.1-security",
15 | "got": "^14.4.2",
16 | "http-proxy-agent": "^7.0.2",
17 | "https-proxy-agent": "^7.0.5",
18 | "node-fetch": "^3.3.2",
19 | "socks-proxy-agent": "^8.0.4"
20 | }
21 | },
22 | "node_modules/@sec-ant/readable-stream": {
23 | "version": "0.4.1",
24 | "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
25 | "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==",
26 | "license": "MIT"
27 | },
28 | "node_modules/@sindresorhus/is": {
29 | "version": "7.0.0",
30 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.0.0.tgz",
31 | "integrity": "sha512-WDTlVTyvFivSOuyvMeedzg2hdoBLZ3f1uNVuEida2Rl9BrfjrIRjWA/VZIrMRLvSwJYCAlCRA3usDt1THytxWQ==",
32 | "license": "MIT",
33 | "engines": {
34 | "node": ">=18"
35 | },
36 | "funding": {
37 | "url": "https://github.com/sindresorhus/is?sponsor=1"
38 | }
39 | },
40 | "node_modules/@szmarczak/http-timer": {
41 | "version": "5.0.1",
42 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz",
43 | "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==",
44 | "license": "MIT",
45 | "dependencies": {
46 | "defer-to-connect": "^2.0.1"
47 | },
48 | "engines": {
49 | "node": ">=14.16"
50 | }
51 | },
52 | "node_modules/@types/http-cache-semantics": {
53 | "version": "4.0.4",
54 | "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
55 | "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==",
56 | "license": "MIT"
57 | },
58 | "node_modules/agent-base": {
59 | "version": "7.1.1",
60 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
61 | "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
62 | "license": "MIT",
63 | "dependencies": {
64 | "debug": "^4.3.4"
65 | },
66 | "engines": {
67 | "node": ">= 14"
68 | }
69 | },
70 | "node_modules/asynckit": {
71 | "version": "0.4.0",
72 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
73 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
74 | "license": "MIT"
75 | },
76 | "node_modules/axios": {
77 | "version": "1.7.7",
78 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
79 | "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
80 | "license": "MIT",
81 | "dependencies": {
82 | "follow-redirects": "^1.15.6",
83 | "form-data": "^4.0.0",
84 | "proxy-from-env": "^1.1.0"
85 | }
86 | },
87 | "node_modules/cacheable-lookup": {
88 | "version": "7.0.0",
89 | "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz",
90 | "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==",
91 | "license": "MIT",
92 | "engines": {
93 | "node": ">=14.16"
94 | }
95 | },
96 | "node_modules/cacheable-request": {
97 | "version": "12.0.1",
98 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-12.0.1.tgz",
99 | "integrity": "sha512-Yo9wGIQUaAfIbk+qY0X4cDQgCosecfBe3V9NSyeY4qPC2SAkbCS4Xj79VP8WOzitpJUZKc/wsRCYF5ariDIwkg==",
100 | "license": "MIT",
101 | "dependencies": {
102 | "@types/http-cache-semantics": "^4.0.4",
103 | "get-stream": "^9.0.1",
104 | "http-cache-semantics": "^4.1.1",
105 | "keyv": "^4.5.4",
106 | "mimic-response": "^4.0.0",
107 | "normalize-url": "^8.0.1",
108 | "responselike": "^3.0.0"
109 | },
110 | "engines": {
111 | "node": ">=18"
112 | }
113 | },
114 | "node_modules/chrome-remote-interface": {
115 | "version": "0.33.2",
116 | "resolved": "https://registry.npmjs.org/chrome-remote-interface/-/chrome-remote-interface-0.33.2.tgz",
117 | "integrity": "sha512-wvm9cOeBTrb218EC+6DteGt92iXr2iY0+XJP30f15JVDhqvWvJEVACh9GvUm8b9Yd8bxQivaLSb8k7mgrbyomQ==",
118 | "dependencies": {
119 | "commander": "2.11.x",
120 | "ws": "^7.2.0"
121 | },
122 | "bin": {
123 | "chrome-remote-interface": "bin/client.js"
124 | }
125 | },
126 | "node_modules/chrome-remote-interface/node_modules/ws": {
127 | "version": "7.5.10",
128 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
129 | "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
130 | "engines": {
131 | "node": ">=8.3.0"
132 | },
133 | "peerDependencies": {
134 | "bufferutil": "^4.0.1",
135 | "utf-8-validate": "^5.0.2"
136 | },
137 | "peerDependenciesMeta": {
138 | "bufferutil": {
139 | "optional": true
140 | },
141 | "utf-8-validate": {
142 | "optional": true
143 | }
144 | }
145 | },
146 | "node_modules/combined-stream": {
147 | "version": "1.0.8",
148 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
149 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
150 | "license": "MIT",
151 | "dependencies": {
152 | "delayed-stream": "~1.0.0"
153 | },
154 | "engines": {
155 | "node": ">= 0.8"
156 | }
157 | },
158 | "node_modules/commander": {
159 | "version": "2.11.0",
160 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
161 | "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ=="
162 | },
163 | "node_modules/data-uri-to-buffer": {
164 | "version": "4.0.1",
165 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
166 | "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
167 | "license": "MIT",
168 | "engines": {
169 | "node": ">= 12"
170 | }
171 | },
172 | "node_modules/debug": {
173 | "version": "4.3.6",
174 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
175 | "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
176 | "license": "MIT",
177 | "dependencies": {
178 | "ms": "2.1.2"
179 | },
180 | "engines": {
181 | "node": ">=6.0"
182 | },
183 | "peerDependenciesMeta": {
184 | "supports-color": {
185 | "optional": true
186 | }
187 | }
188 | },
189 | "node_modules/decompress-response": {
190 | "version": "6.0.0",
191 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
192 | "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
193 | "license": "MIT",
194 | "dependencies": {
195 | "mimic-response": "^3.1.0"
196 | },
197 | "engines": {
198 | "node": ">=10"
199 | },
200 | "funding": {
201 | "url": "https://github.com/sponsors/sindresorhus"
202 | }
203 | },
204 | "node_modules/decompress-response/node_modules/mimic-response": {
205 | "version": "3.1.0",
206 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
207 | "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
208 | "license": "MIT",
209 | "engines": {
210 | "node": ">=10"
211 | },
212 | "funding": {
213 | "url": "https://github.com/sponsors/sindresorhus"
214 | }
215 | },
216 | "node_modules/defer-to-connect": {
217 | "version": "2.0.1",
218 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
219 | "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
220 | "license": "MIT",
221 | "engines": {
222 | "node": ">=10"
223 | }
224 | },
225 | "node_modules/delayed-stream": {
226 | "version": "1.0.0",
227 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
228 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
229 | "license": "MIT",
230 | "engines": {
231 | "node": ">=0.4.0"
232 | }
233 | },
234 | "node_modules/fetch-blob": {
235 | "version": "3.2.0",
236 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
237 | "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
238 | "funding": [
239 | {
240 | "type": "github",
241 | "url": "https://github.com/sponsors/jimmywarting"
242 | },
243 | {
244 | "type": "paypal",
245 | "url": "https://paypal.me/jimmywarting"
246 | }
247 | ],
248 | "license": "MIT",
249 | "dependencies": {
250 | "node-domexception": "^1.0.0",
251 | "web-streams-polyfill": "^3.0.3"
252 | },
253 | "engines": {
254 | "node": "^12.20 || >= 14.13"
255 | }
256 | },
257 | "node_modules/follow-redirects": {
258 | "version": "1.15.6",
259 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
260 | "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
261 | "funding": [
262 | {
263 | "type": "individual",
264 | "url": "https://github.com/sponsors/RubenVerborgh"
265 | }
266 | ],
267 | "license": "MIT",
268 | "engines": {
269 | "node": ">=4.0"
270 | },
271 | "peerDependenciesMeta": {
272 | "debug": {
273 | "optional": true
274 | }
275 | }
276 | },
277 | "node_modules/form-data": {
278 | "version": "4.0.0",
279 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
280 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
281 | "license": "MIT",
282 | "dependencies": {
283 | "asynckit": "^0.4.0",
284 | "combined-stream": "^1.0.8",
285 | "mime-types": "^2.1.12"
286 | },
287 | "engines": {
288 | "node": ">= 6"
289 | }
290 | },
291 | "node_modules/form-data-encoder": {
292 | "version": "4.0.2",
293 | "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-4.0.2.tgz",
294 | "integrity": "sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==",
295 | "license": "MIT",
296 | "engines": {
297 | "node": ">= 18"
298 | }
299 | },
300 | "node_modules/formdata-polyfill": {
301 | "version": "4.0.10",
302 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
303 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
304 | "license": "MIT",
305 | "dependencies": {
306 | "fetch-blob": "^3.1.2"
307 | },
308 | "engines": {
309 | "node": ">=12.20.0"
310 | }
311 | },
312 | "node_modules/fs": {
313 | "version": "0.0.1-security",
314 | "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
315 | "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==",
316 | "license": "ISC"
317 | },
318 | "node_modules/get-stream": {
319 | "version": "9.0.1",
320 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz",
321 | "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==",
322 | "license": "MIT",
323 | "dependencies": {
324 | "@sec-ant/readable-stream": "^0.4.1",
325 | "is-stream": "^4.0.1"
326 | },
327 | "engines": {
328 | "node": ">=18"
329 | },
330 | "funding": {
331 | "url": "https://github.com/sponsors/sindresorhus"
332 | }
333 | },
334 | "node_modules/got": {
335 | "version": "14.4.2",
336 | "resolved": "https://registry.npmjs.org/got/-/got-14.4.2.tgz",
337 | "integrity": "sha512-+Te/qEZ6hr7i+f0FNgXx/6WQteSM/QqueGvxeYQQFm0GDfoxLVJ/oiwUKYMTeioColWUTdewZ06hmrBjw6F7tw==",
338 | "license": "MIT",
339 | "dependencies": {
340 | "@sindresorhus/is": "^7.0.0",
341 | "@szmarczak/http-timer": "^5.0.1",
342 | "cacheable-lookup": "^7.0.0",
343 | "cacheable-request": "^12.0.1",
344 | "decompress-response": "^6.0.0",
345 | "form-data-encoder": "^4.0.2",
346 | "http2-wrapper": "^2.2.1",
347 | "lowercase-keys": "^3.0.0",
348 | "p-cancelable": "^4.0.1",
349 | "responselike": "^3.0.0",
350 | "type-fest": "^4.19.0"
351 | },
352 | "engines": {
353 | "node": ">=20"
354 | },
355 | "funding": {
356 | "url": "https://github.com/sindresorhus/got?sponsor=1"
357 | }
358 | },
359 | "node_modules/http-cache-semantics": {
360 | "version": "4.1.1",
361 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
362 | "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
363 | "license": "BSD-2-Clause"
364 | },
365 | "node_modules/http-proxy-agent": {
366 | "version": "7.0.2",
367 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
368 | "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
369 | "license": "MIT",
370 | "dependencies": {
371 | "agent-base": "^7.1.0",
372 | "debug": "^4.3.4"
373 | },
374 | "engines": {
375 | "node": ">= 14"
376 | }
377 | },
378 | "node_modules/http2-wrapper": {
379 | "version": "2.2.1",
380 | "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz",
381 | "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==",
382 | "license": "MIT",
383 | "dependencies": {
384 | "quick-lru": "^5.1.1",
385 | "resolve-alpn": "^1.2.0"
386 | },
387 | "engines": {
388 | "node": ">=10.19.0"
389 | }
390 | },
391 | "node_modules/https-proxy-agent": {
392 | "version": "7.0.5",
393 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
394 | "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
395 | "license": "MIT",
396 | "dependencies": {
397 | "agent-base": "^7.0.2",
398 | "debug": "4"
399 | },
400 | "engines": {
401 | "node": ">= 14"
402 | }
403 | },
404 | "node_modules/ip-address": {
405 | "version": "9.0.5",
406 | "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
407 | "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
408 | "license": "MIT",
409 | "dependencies": {
410 | "jsbn": "1.1.0",
411 | "sprintf-js": "^1.1.3"
412 | },
413 | "engines": {
414 | "node": ">= 12"
415 | }
416 | },
417 | "node_modules/is-stream": {
418 | "version": "4.0.1",
419 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz",
420 | "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==",
421 | "license": "MIT",
422 | "engines": {
423 | "node": ">=18"
424 | },
425 | "funding": {
426 | "url": "https://github.com/sponsors/sindresorhus"
427 | }
428 | },
429 | "node_modules/jsbn": {
430 | "version": "1.1.0",
431 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
432 | "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
433 | "license": "MIT"
434 | },
435 | "node_modules/json-buffer": {
436 | "version": "3.0.1",
437 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
438 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
439 | "license": "MIT"
440 | },
441 | "node_modules/keyv": {
442 | "version": "4.5.4",
443 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
444 | "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
445 | "license": "MIT",
446 | "dependencies": {
447 | "json-buffer": "3.0.1"
448 | }
449 | },
450 | "node_modules/lowercase-keys": {
451 | "version": "3.0.0",
452 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
453 | "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==",
454 | "license": "MIT",
455 | "engines": {
456 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
457 | },
458 | "funding": {
459 | "url": "https://github.com/sponsors/sindresorhus"
460 | }
461 | },
462 | "node_modules/mime-db": {
463 | "version": "1.52.0",
464 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
465 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
466 | "license": "MIT",
467 | "engines": {
468 | "node": ">= 0.6"
469 | }
470 | },
471 | "node_modules/mime-types": {
472 | "version": "2.1.35",
473 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
474 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
475 | "license": "MIT",
476 | "dependencies": {
477 | "mime-db": "1.52.0"
478 | },
479 | "engines": {
480 | "node": ">= 0.6"
481 | }
482 | },
483 | "node_modules/mimic-response": {
484 | "version": "4.0.0",
485 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz",
486 | "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==",
487 | "license": "MIT",
488 | "engines": {
489 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
490 | },
491 | "funding": {
492 | "url": "https://github.com/sponsors/sindresorhus"
493 | }
494 | },
495 | "node_modules/ms": {
496 | "version": "2.1.2",
497 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
498 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
499 | "license": "MIT"
500 | },
501 | "node_modules/node-domexception": {
502 | "version": "1.0.0",
503 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
504 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
505 | "funding": [
506 | {
507 | "type": "github",
508 | "url": "https://github.com/sponsors/jimmywarting"
509 | },
510 | {
511 | "type": "github",
512 | "url": "https://paypal.me/jimmywarting"
513 | }
514 | ],
515 | "license": "MIT",
516 | "engines": {
517 | "node": ">=10.5.0"
518 | }
519 | },
520 | "node_modules/node-fetch": {
521 | "version": "3.3.2",
522 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
523 | "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
524 | "license": "MIT",
525 | "dependencies": {
526 | "data-uri-to-buffer": "^4.0.0",
527 | "fetch-blob": "^3.1.4",
528 | "formdata-polyfill": "^4.0.10"
529 | },
530 | "engines": {
531 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
532 | },
533 | "funding": {
534 | "type": "opencollective",
535 | "url": "https://opencollective.com/node-fetch"
536 | }
537 | },
538 | "node_modules/normalize-url": {
539 | "version": "8.0.1",
540 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz",
541 | "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==",
542 | "license": "MIT",
543 | "engines": {
544 | "node": ">=14.16"
545 | },
546 | "funding": {
547 | "url": "https://github.com/sponsors/sindresorhus"
548 | }
549 | },
550 | "node_modules/p-cancelable": {
551 | "version": "4.0.1",
552 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-4.0.1.tgz",
553 | "integrity": "sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==",
554 | "license": "MIT",
555 | "engines": {
556 | "node": ">=14.16"
557 | }
558 | },
559 | "node_modules/proxy-from-env": {
560 | "version": "1.1.0",
561 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
562 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
563 | "license": "MIT"
564 | },
565 | "node_modules/quick-lru": {
566 | "version": "5.1.1",
567 | "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
568 | "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
569 | "license": "MIT",
570 | "engines": {
571 | "node": ">=10"
572 | },
573 | "funding": {
574 | "url": "https://github.com/sponsors/sindresorhus"
575 | }
576 | },
577 | "node_modules/resolve-alpn": {
578 | "version": "1.2.1",
579 | "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
580 | "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
581 | "license": "MIT"
582 | },
583 | "node_modules/responselike": {
584 | "version": "3.0.0",
585 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz",
586 | "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==",
587 | "license": "MIT",
588 | "dependencies": {
589 | "lowercase-keys": "^3.0.0"
590 | },
591 | "engines": {
592 | "node": ">=14.16"
593 | },
594 | "funding": {
595 | "url": "https://github.com/sponsors/sindresorhus"
596 | }
597 | },
598 | "node_modules/smart-buffer": {
599 | "version": "4.2.0",
600 | "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
601 | "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
602 | "license": "MIT",
603 | "engines": {
604 | "node": ">= 6.0.0",
605 | "npm": ">= 3.0.0"
606 | }
607 | },
608 | "node_modules/socks": {
609 | "version": "2.8.3",
610 | "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
611 | "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
612 | "license": "MIT",
613 | "dependencies": {
614 | "ip-address": "^9.0.5",
615 | "smart-buffer": "^4.2.0"
616 | },
617 | "engines": {
618 | "node": ">= 10.0.0",
619 | "npm": ">= 3.0.0"
620 | }
621 | },
622 | "node_modules/socks-proxy-agent": {
623 | "version": "8.0.4",
624 | "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz",
625 | "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==",
626 | "license": "MIT",
627 | "dependencies": {
628 | "agent-base": "^7.1.1",
629 | "debug": "^4.3.4",
630 | "socks": "^2.8.3"
631 | },
632 | "engines": {
633 | "node": ">= 14"
634 | }
635 | },
636 | "node_modules/sprintf-js": {
637 | "version": "1.1.3",
638 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
639 | "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
640 | "license": "BSD-3-Clause"
641 | },
642 | "node_modules/type-fest": {
643 | "version": "4.26.0",
644 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.0.tgz",
645 | "integrity": "sha512-OduNjVJsFbifKb57UqZ2EMP1i4u64Xwow3NYXUtBbD4vIwJdQd4+xl8YDou1dlm4DVrtwT/7Ky8z8WyCULVfxw==",
646 | "license": "(MIT OR CC0-1.0)",
647 | "engines": {
648 | "node": ">=16"
649 | },
650 | "funding": {
651 | "url": "https://github.com/sponsors/sindresorhus"
652 | }
653 | },
654 | "node_modules/web-streams-polyfill": {
655 | "version": "3.3.3",
656 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
657 | "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
658 | "license": "MIT",
659 | "engines": {
660 | "node": ">= 8"
661 | }
662 | }
663 | }
664 | }
665 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cloudfreed",
3 | "contributors": [
4 | "Akmal",
5 | "TheRealStingo"
6 | ],
7 | "type": "module",
8 | "version": "3.1.1",
9 | "description": "CloudFreed, an automated cloudflare solver.",
10 | "repository": {
11 | "type": "git",
12 | "url": "git://github.com/Akmal-CloudFreed/CloudFreed---CloudFlare-bypass.git"
13 | },
14 | "main": "index.js",
15 | "scripts": {
16 | "test": "echo \"Error: no test specified\" && exit 1"
17 | },
18 | "author": "Akmal",
19 | "license": "ISC",
20 | "dependencies": {
21 | "axios": "^1.7.7",
22 | "chrome-remote-interface": "^0.33.2",
23 | "fs": "^0.0.1-security",
24 | "got": "^14.4.2",
25 | "http-proxy-agent": "^7.0.2",
26 | "https-proxy-agent": "^7.0.5",
27 | "node-fetch": "^3.3.2",
28 | "socks-proxy-agent": "^8.0.4"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------