{"id":13588500,"url":"https://github.com/NoahCardoza/CloudProxy","last_synced_at":"2025-04-08T06:32:07.295Z","repository":{"id":37616033,"uuid":"278585018","full_name":"NoahCardoza/CloudProxy","owner":"NoahCardoza","description":"Proxy server to bypass Cloudflare protection.","archived":false,"fork":false,"pushed_at":"2023-10-03T00:45:01.000Z","size":581,"stargazers_count":545,"open_issues_count":19,"forks_count":62,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-04-04T14:07:20.523Z","etag":null,"topics":["anti-bot-page","cloudflare","cloudflare-bypass","cloudflare-scrape","hacktoberfest","sneakerbot"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NoahCardoza.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-10T08:48:41.000Z","updated_at":"2025-04-01T09:45:58.000Z","dependencies_parsed_at":"2024-10-24T13:13:21.217Z","dependency_job_id":"0cbdc5ca-4f42-4000-8dec-05c622ad4929","html_url":"https://github.com/NoahCardoza/CloudProxy","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoahCardoza%2FCloudProxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoahCardoza%2FCloudProxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoahCardoza%2FCloudProxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoahCardoza%2FCloudProxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NoahCardoza","download_url":"https://codeload.github.com/NoahCardoza/CloudProxy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247792086,"owners_count":20996877,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anti-bot-page","cloudflare","cloudflare-bypass","cloudflare-scrape","hacktoberfest","sneakerbot"],"created_at":"2024-08-01T15:06:45.287Z","updated_at":"2025-04-08T06:32:07.240Z","avatar_url":"https://github.com/NoahCardoza.png","language":"TypeScript","funding_links":["https://www.buymeacoffee.com/noahcardoza"],"categories":["TypeScript"],"sub_categories":[],"readme":"# CloudProxy\r\n\r\nProxy server to bypass Cloudflare protection\r\n\r\n:warning: This project is in beta state. Some things may not work and the API can change at any time.\r\nSee the known issues section.\r\n\r\n# 2captcha Alternatives\r\n\r\n## [CapSolver.com](https://dashboard.capsolver.com/passport/register?inviteCode=45JrWKeetsQa)\r\n\r\n\u003cp align=\"center\"\u003e\r\n  \u003ca href=\"https://dashboard.capsolver.com/passport/register?inviteCode=45JrWKeetsQa\"\u003e\r\n    \u003cimg src=\"https://i.imgur.com/YaRmSt4.gif\" alt=\"Capsolver's Banner\" style=\"width: 100%;\"\u003e\r\n  \u003c/a\u003e\r\n\u003c/p\u003e\r\n\r\n\u003ca href=\"https://dashboard.capsolver.com/passport/register?inviteCode=45JrWKeetsQa\"\u003eCapsolver\u003c/a\u003e offers an affordable and quick automatic captcha solving solution with a success rate of 99.15% and the ability to solve a variety of captchas, including reCAPTCHA V2, hCaptcha, FunCaptcha, and more. Integration with various API clients is also supported, and a free trial balance is available with upgraded personal details.\r\n\r\n## Discord\r\n\r\nIf you need help feel free to swing by my [Discord](https://discord.gg/gTq2VmUMsE)!\r\n\r\n## How it works\r\n\r\nCloudProxy starts a proxy server and it waits for user requests in an idle state using few resources.\r\nWhen some request arrives, it uses [puppeteer](https://github.com/puppeteer/puppeteer) with the\r\n[stealth plugin](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth)\r\nto create a headless browser (Chrome). It opens the URL with user parameters and waits until the\r\nCloudflare challenge is solved (or timeout). The HTML code and the cookies are sent back to the\r\nuser and those cookies can be used to bypass Cloudflare using other HTTP clients.\r\n\r\n**NOTE**: Web browsers consume a lot of memory. If you are running CloudProxy on a machine with few RAM,\r\ndo not make many requests at once. With each request a new browser is launched unless you use a session ID which is strongly recommended. However, if you use sessions, you should make sure to close them as soon as you are done using them.\r\n\r\n## Installation\r\n\r\nIt requires NodeJS.\r\n\r\nRun `PUPPETEER_PRODUCT=chrome npm install` to install CloudProxy dependencies.\r\n\r\n## Usage\r\n\r\nFirst run `npm run build`. Once the TypeScript is compiled, you can use `npm start` to start CloudProxy.\r\n\r\nExample request:\r\n\r\n```bash\r\ncurl -L -X POST 'http://localhost:8191/v1' \\\r\n-H 'Content-Type: application/json' \\\r\n--data-raw '{\r\n  \"cmd\": \"request.get\",\r\n  \"url\":\"http://www.google.com/\",\r\n  \"userAgent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.0 Safari/537.36\",\r\n  \"maxTimeout\": 60000,\r\n  \"headers\": {\r\n    \"X-Test\": \"Testing 123...\"\r\n  }\r\n}'\r\n```\r\n\r\n### Commands\r\n\r\n#### + `sessions.create`\r\n\r\nThis will launch a new browser instance which will retain cookies until you destroy it\r\nwith `sessions.destroy`. This comes in handy so you don't have to keep solving challenges\r\nover and over and you won't need to keep sending cookies for the browser to use.\r\n\r\nThis also speeds up the requests since it won't have to launch a new browser instance for\r\nevery request.\r\n\r\nParameter | Notes\r\n|--|--|\r\nsession | Optional. The session ID that you want to be assinged to the instance. If one isn't set a random UUID will be assigned.\r\nuserAgent | Optional. Will be used by the headless browser.\r\n\r\n#### + `sessions.list`\r\n\r\nReturns a list of all the active sessions. More for debuging if you are curious to see\r\nhow many sessions are running. You should always make sure to properly close each\r\nsession when you are done using them as too many may slow your computer down.\r\n\r\nExample response:\r\n\r\n```json\r\n{\r\n  \"sessions\": [\r\n    \"session_id_1\",\r\n    \"session_id_2\",\r\n    \"session_id_3...\"\r\n  ]\r\n}\r\n```\r\n\r\n#### + `sessions.destroy`\r\n\r\nThis will properly shutdown a browser instance and remove all files associaded with it\r\nto free up resources for a new session. Whenever you no longer need to use a session you\r\nshould make sure to close it.\r\n\r\nParameter | Notes\r\n|--|--|\r\nsession | The session ID that you want to be destroyed.\r\n\r\n#### + `request.get`\r\n\r\nParameter | Notes\r\n|--|--|\r\nurl | Mandatory\r\nsession | Optional. Will send the request from and existing browser instance. If one is not sent it will create a temporary instance that will be destroyed immediately after the request is completed.\r\nheaders | Optional. To specify user headers.\r\nmaxTimeout | Optional. Max timeout to solve the challenge\r\ncookies | Optional. Will be used by the headless browser. Follow [this](https://github.com/puppeteer/puppeteer/blob/v3.3.0/docs/api.md#pagesetcookiecookies) format\r\nencode | Optional. Add to header list `'Content-Type': 'application/x-www-form-urlencoded'` — can be useful if you need to send a JSON in `postData`.\r\nExample response from running the `curl` above:\r\n\r\n```json\r\n{\r\n    \"solution\": {\r\n        \"url\": \"https://www.google.com/?gws_rd=ssl\",\r\n        \"status\": 200,\r\n        \"headers\": {\r\n            \"status\": \"200\",\r\n            \"date\": \"Thu, 16 Jul 2020 04:15:49 GMT\",\r\n            \"expires\": \"-1\",\r\n            \"cache-control\": \"private, max-age=0\",\r\n            \"content-type\": \"text/html; charset=UTF-8\",\r\n            \"strict-transport-security\": \"max-age=31536000\",\r\n            \"p3p\": \"CP=\\\"This is not a P3P policy! See g.co/p3phelp for more info.\\\"\",\r\n            \"content-encoding\": \"br\",\r\n            \"server\": \"gws\",\r\n            \"content-length\": \"61587\",\r\n            \"x-xss-protection\": \"0\",\r\n            \"x-frame-options\": \"SAMEORIGIN\",\r\n            \"set-cookie\": \"1P_JAR=2020-07-16-04; expires=Sat, 15-Aug-2020 04:15:49 GMT; path=/; domain=.google.com; Secure; SameSite=none\\nNID=204=QE3Ocq15XalczqjuDy52HeseG3zAZuJzID3R57g_oeQHyoV5DuvDhpWc4r9IcPoeIYmkr_ZTX_MNOU8IAbtXmVO7Bmq0adb-hpIHaTBIdBk3Ofifp4gO6vZleVuFYfj7ePkHeHdzGoX-en0FvKtd9iofX4O6RiAdEIAnpL7Wge4; expires=Fri, 15-Jan-2021 04:15:49 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=none\",\r\n            \"alt-svc\": \"h3-29=\\\":443\\\"; ma=2592000,h3-27=\\\":443\\\"; ma=2592000,h3-25=\\\":443\\\"; ma=2592000,h3-T050=\\\":443\\\"; ma=2592000,h3-Q050=\\\":443\\\"; ma=2592000,h3-Q046=\\\":443\\\"; ma=2592000,h3-Q043=\\\":443\\\"; ma=2592000,quic=\\\":443\\\"; ma=2592000; v=\\\"46,43\\\"\"\r\n        },\r\n        \"response\":\"\u003c!DOCTYPE html\u003e...\",\r\n        \"cookies\": [\r\n            {\r\n                \"name\": \"NID\",\r\n                \"value\": \"204=QE3Ocq15XalczqjuDy52HeseG3zAZuJzID3R57g_oeQHyoV5DuvDhpWc4r9IcPoeIYmkr_ZTX_MNOU8IAbtXmVO7Bmq0adb-hpIHaTBIdBk3Ofifp4gO6vZleVuFYfj7ePkHeHdzGoX-en0FvKtd9iofX4O6RiAdEIAnpL7Wge4\",\r\n                \"domain\": \".google.com\",\r\n                \"path\": \"/\",\r\n                \"expires\": 1610684149.307722,\r\n                \"size\": 178,\r\n                \"httpOnly\": true,\r\n                \"secure\": true,\r\n                \"session\": false,\r\n                \"sameSite\": \"None\"\r\n            },\r\n            {\r\n                \"name\": \"1P_JAR\",\r\n                \"value\": \"2020-07-16-04\",\r\n                \"domain\": \".google.com\",\r\n                \"path\": \"/\",\r\n                \"expires\": 1597464949.307626,\r\n                \"size\": 19,\r\n                \"httpOnly\": false,\r\n                \"secure\": true,\r\n                \"session\": false,\r\n                \"sameSite\": \"None\"\r\n            }\r\n        ],\r\n        \"userAgent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.0 Safari/537.36\"\r\n    },\r\n    \"status\": \"ok\",\r\n    \"message\": \"\",\r\n    \"startTimestamp\": 1594872947467,\r\n    \"endTimestamp\": 1594872949617,\r\n    \"version\": \"1.0.0\"\r\n}\r\n```\r\n\r\n### + `request.post`\r\n\r\nThis is the same as `request.get` but it takes one more param:\r\n\r\nExample request:\r\n\r\n```bash\r\ncurl -L -X POST 'http://localhost:8191/v1' \\\r\n-H 'Content-Type: application/json' \\\r\n--data-raw '{\r\n  \"cmd\": \"request.post\",\r\n  \"url\":\"http://www.google.com/\",\r\n  \"userAgent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.0 Safari/537.36\",\r\n  \"maxTimeout\": 60000,\r\n  \"postData\": { \"string\": \"string\", \"number\": 10, \"boolean\": false },\r\n  \"headers\": {\r\n    \"X-Test\": \"Testing 123...\"\r\n  }\r\n}'\r\n```\r\nParameter | Notes\r\n|--|--|\r\npostData | Must be a object.\r\n\r\n## Downloading Images and PDFs (small files)\r\n\r\nIf you need to access an image/pdf or small file, you should pass the `download` parameter to\r\n`request.get` setting it to `true`. Rather than access the html and return text it will\r\nreturn a the buffer **base64** encoded which you will be able to decode and save the image/pdf.\r\n\r\nThis method isn't recommended for videos or anything larger. As that should be streamed back to\r\nthe client and at the moment there is nothing setup to do so. If this is something you need feel\r\nfree to create an issue and/or submit a PR.\r\n\r\n## Environment variables\r\n\r\nTo set the environment vars in Linux run `export LOG_LEVEL=debug` and then start CloudProxy in the same shell.\r\n\r\nName | Default | Notes\r\n|--|--|--|\r\nLOG_LEVEL | info | Used to change the verbosity of the logging.\r\nLOG_HTML | false | Used for debugging. If `true` all html that passes through the proxy will be logged to the console.\r\nPORT | 8191 | Change this if you already have a process running on port `8191`.\r\nHOST | 0.0.0.0 | This shouldn't need to be messed with but if you insist, it's here!\r\nCAPTCHA_SOLVER | None | This is used to select which captcha solving method it used when a captcha is encounted.\r\nHEADLESS | true | This is used to debug the browser by not running it in headless mode.\r\n\r\n## Captcha Solvers\r\n\r\nSometimes CF not only gives mathmatical computations and browser tests, sometimes they also require\r\nthe user to solve a captcha. If this is the case, CloudProxy will return the captcha page. But that's\r\nnot very helpful to you is it?\r\n\r\nCloudProxy can be customized to solve the captcha's automatically by setting the environment variable\r\n`CAPTCHA_SOLVER` to the file name of one of the adapters inside the [/captcha](src/captcha) directory.\r\n\r\n### [CaptchaHarvester](https://github.com/NoahCardoza/CaptchaHarvester)\r\n\r\nThis method makes use of the [CaptchaHarvester](https://github.com/NoahCardoza/CaptchaHarvester) project which allows users to collect thier own tokens from ReCaptcha V2/V3 and hCaptcha for free.\r\n\r\nTo use this method you must set these ENV variables:\r\n\r\n```bash\r\nCAPTCHA_SOLVER=harvester\r\nHARVESTER_ENDPOINT=https://127.0.0.1:5000/token\r\n```\r\n\r\n**Note**: above I set `HARVESTER_ENDPOINT` to the default configureation\r\nof the captcha harvester's server, but that could change if\r\nyou customize the command line flags. Simply put, `HARVESTER_ENDPOINT`\r\nshould be set to the URI of the route that returns a token in plain text when called.\r\n\r\n### [hcaptcha-solver](https://github.com/JimmyLaurent/hcaptcha-solver)\r\n\r\nThis method makes use of the [hcaptcha-solver](https://github.com/JimmyLaurent/hcaptcha-solver) project which attempts to solve hcaptcha by randomly selecting images.\r\n\r\nTo use this solver you must first install it and then set it as the `CAPTCHA_SOLVER`.\r\n\r\n```bash\r\nnpm i hcaptcha-solver\r\nCAPTCHA_SOLVER=hcaptcha-solver\r\n```\r\n\r\n### Other Options\r\n\r\nEveryone likes more options to choose from. Help contribute to the projects by submitting\r\nPR requests for other 3rd party captcha solves or your own projects.\r\nPR's are welcome for any and all captcha solving methods and services.\r\n\r\n## Docker\r\n\r\nYou may edit the `./Dockerfile` as well as `./docker-compose.yml` as you see fit.\r\n\r\n```bash\r\n# To build the image \u0026 run it using `docker compose` (detched mode)\r\ndocker compose up -d\r\n\r\n# To stop \u0026 remove containers:\r\ndocker compose down\r\n\r\n# You may also build and run manually, however the configuration is\r\n# already set in the compose file, that way you dont have to remember it.\r\ndocker build -t cloudproxy:latest .\r\ndocker run --restart=always --name cloudproxy -p 8191:8191 -d cloudproxy:latest\r\n```\r\n\r\n## TypeScript\r\n\r\nI'm quite new to TypeScript. If you spot any funny business or anything that is or isn't being\r\nused properly feel free to submit a PR or open an issue.\r\n\r\n## Known issues / Roadmap\r\n\r\nThe current implementation seems to be working on the sites I have been testing them on. However, if you find it unable to access a site, open an issue and I'd be happy to investigate.\r\n\r\nThat being said, the project uses the [puppeteer stealth plugin](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth). If Cloudflare is able to detect the headless browser, it's more that projects domain to fix.\r\n\r\nTODO:\r\n\r\n* Fix remaining issues in the code (see TODOs in code)\r\n* Make the maxTimeout more accurate (count the time to open the first page / maybe count the captcha solve time?)\r\n* Hide sensitive information in logs\r\n* Reduce Docker image size\r\n* Docker image for ARM architecture\r\n* Install instructions for Windows\r\n\r\n## Credits\r\n\r\nBased off of ngosang's [FlareSolverr](https://github.com/ngosang/FlareSolverr).\r\n\r\nFor help contact @`MacHacker#7322` (Discord)\r\n\r\nHas CloudProxy saved or made you money on your project? Consider buying me a coffee!\r\n\r\n[![Buy Me A Coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/noahcardoza)\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNoahCardoza%2FCloudProxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FNoahCardoza%2FCloudProxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNoahCardoza%2FCloudProxy/lists"}