├── .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 | [![Discord](https://img.shields.io/discord/1219437599740002445.svg?label=Discord&logo=discord&colorB=7289DA)](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 | CloudFreed Logo 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 |
35 |
36 |
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 | --------------------------------------------------------------------------------