├── .gitignore ├── examples ├── media │ ├── canvas.png │ ├── example.mp3 │ ├── boundingBox.jpg │ ├── coordinates.jpg │ ├── rotatecaptcha.png │ ├── recaptchaGrid3x3.jpg │ ├── recaptchaGrid4x4.jpg │ ├── imageCaptcha_6e584.png │ ├── canvasImgInstructions.jpg │ ├── boundingBoxImginstructions.jpg │ └── recaptchaGridImginstructions4x4.jpg ├── text.js ├── tencent.js ├── mtCaptcha.js ├── turnstile.js ├── geetestV4.js ├── capyPuzzle.js ├── yandexSmart.js ├── recaptcha_v2.js ├── friendlyCaptcha.js ├── cutcaptcha.js ├── atbcaptcha.js ├── audio.js ├── funcaptcha.js ├── lemin.js ├── balance.js ├── coordinates.js ├── recaptcha_v3.js ├── rotate.js ├── cyberSiARA.js ├── keyCaptcha.js ├── imageCaptcha.js ├── canvas.js ├── grid.js ├── boundingBox.js ├── dataDome.js ├── reports.js ├── amazonWaf.js ├── grid_options.js └── geetest.js ├── src ├── utils │ ├── fetch.ts │ ├── renameParams.ts │ ├── generic.ts │ └── checkCaptchaParams.ts ├── index.ts └── structs │ ├── constants │ └── constants.ts │ ├── providers │ └── providers.ts │ ├── solvecaptchaServer.ts │ ├── solvecaptchaError.ts │ └── solvecaptcha.ts ├── .npmignore ├── jsdoc.json ├── LICENSE ├── .github └── workflows │ └── publish.yml ├── RELEASING.md ├── package.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── tsconfig.json ├── yarn.lock └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Directories 2 | /dist 3 | /node_modules 4 | /out 5 | 6 | # Files 7 | .env -------------------------------------------------------------------------------- /examples/media/canvas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvercaptcha/solvecaptcha-javascript/HEAD/examples/media/canvas.png -------------------------------------------------------------------------------- /examples/media/example.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvercaptcha/solvecaptcha-javascript/HEAD/examples/media/example.mp3 -------------------------------------------------------------------------------- /examples/media/boundingBox.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvercaptcha/solvecaptcha-javascript/HEAD/examples/media/boundingBox.jpg -------------------------------------------------------------------------------- /examples/media/coordinates.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvercaptcha/solvecaptcha-javascript/HEAD/examples/media/coordinates.jpg -------------------------------------------------------------------------------- /examples/media/rotatecaptcha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvercaptcha/solvecaptcha-javascript/HEAD/examples/media/rotatecaptcha.png -------------------------------------------------------------------------------- /examples/media/recaptchaGrid3x3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvercaptcha/solvecaptcha-javascript/HEAD/examples/media/recaptchaGrid3x3.jpg -------------------------------------------------------------------------------- /examples/media/recaptchaGrid4x4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvercaptcha/solvecaptcha-javascript/HEAD/examples/media/recaptchaGrid4x4.jpg -------------------------------------------------------------------------------- /src/utils/fetch.ts: -------------------------------------------------------------------------------- 1 | import nodeFetch from 'node-fetch'; 2 | 3 | export = typeof window === 'undefined' ? nodeFetch : window.fetch.bind(window) -------------------------------------------------------------------------------- /examples/media/imageCaptcha_6e584.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvercaptcha/solvecaptcha-javascript/HEAD/examples/media/imageCaptcha_6e584.png -------------------------------------------------------------------------------- /examples/media/canvasImgInstructions.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvercaptcha/solvecaptcha-javascript/HEAD/examples/media/canvasImgInstructions.jpg -------------------------------------------------------------------------------- /examples/media/boundingBoxImginstructions.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvercaptcha/solvecaptcha-javascript/HEAD/examples/media/boundingBoxImginstructions.jpg -------------------------------------------------------------------------------- /examples/media/recaptchaGridImginstructions4x4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solvercaptcha/solvecaptcha-javascript/HEAD/examples/media/recaptchaGridImginstructions4x4.jpg -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { Solver } from "./structs/solvecaptcha" 2 | export { APIError } from "./structs/solvecaptchaError" 3 | // export { Server } from "./structs/solvecaptchaServer.js" -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Directories 2 | src/ 3 | node_modules/ 4 | examples/ 5 | tsconfig.json/ 6 | out/ 7 | 8 | # Files 9 | .yarn.lock 10 | .gitignore 11 | readme.md 12 | jsdoc.json 13 | .env -------------------------------------------------------------------------------- /jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates": { 3 | "applicationName": "Solvecaptcha", 4 | "source": { 5 | "include": [ 6 | "./dist/" 7 | ] 8 | }, 9 | "opts": { 10 | "encoding": "utf8", 11 | "recurse": true, 12 | "destination": "./docs", 13 | "template": "./node_modules/jaguarjs-jsdoc" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /examples/text.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.text({ 8 | textcaptcha: "If tomorrow is Saturday, what day is today?", 9 | lang: 'en' 10 | }) 11 | .then((res) => { 12 | console.log(res); 13 | }) 14 | .catch((err) => { 15 | console.log(err); 16 | }) 17 | -------------------------------------------------------------------------------- /examples/tencent.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.tencent({ 8 | pageurl: "https://mysite.com/page/with/tencent", 9 | appId: "189956587" 10 | }) 11 | .then((res) => { 12 | console.log(res); 13 | }) 14 | .catch((err) => { 15 | console.log(err); 16 | }) 17 | -------------------------------------------------------------------------------- /src/structs/constants/constants.ts: -------------------------------------------------------------------------------- 1 | const solveCaptchaName = 'solvecaptcha' 2 | const solveCaptchaIn = 'https://solvecaptcha.com/in.php' 3 | const solveCaptchaRes = 'https://solvecaptcha.com/res.php' 4 | 5 | const softId: number = 4845 6 | 7 | const supportedProviders = { 8 | solveCaptcha: { 9 | name: solveCaptchaName, 10 | in: solveCaptchaIn, 11 | res: solveCaptchaRes 12 | } 13 | } 14 | 15 | export { supportedProviders, softId } 16 | -------------------------------------------------------------------------------- /examples/mtCaptcha.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.mtCaptcha({ 8 | pageurl: "https://service.mtcaptcha.com/mtcv1/demo/index.html", 9 | sitekey: "MTPublic-DemoKey9M" 10 | }) 11 | .then((res) => { 12 | console.log(res); 13 | }) 14 | .catch((err) => { 15 | console.log(err); 16 | }) 17 | -------------------------------------------------------------------------------- /examples/turnstile.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.cloudflareTurnstile({ 8 | pageurl: "https://app.nodecraft.com/login", 9 | sitekey: "0x4AAAAAAAAkg0s3VIOD10y4" 10 | }) 11 | .then((res) => { 12 | console.log(res); 13 | }) 14 | .catch((err) => { 15 | console.log(err); 16 | }) 17 | -------------------------------------------------------------------------------- /examples/geetestV4.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.geetestV4({ 8 | pageurl: 'https://solvecaptcha.com/demo/geetest-v4', 9 | captcha_id: 'e392e1d7fd421dc63325744d5a2b9c73' 10 | }) 11 | .then((res) => { 12 | console.log(res); 13 | }) 14 | .catch((err) => { 15 | console.log(err); 16 | }) 17 | -------------------------------------------------------------------------------- /examples/capyPuzzle.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.capyPuzzle({ 8 | pageurl: "https://www.capy.me/account/register/", 9 | captchakey: "PUZZLE_Cme4hZLjuZRMYC3uh14C52D3uNms5w" 10 | }) 11 | .then((res) => { 12 | console.log(res); 13 | }) 14 | .catch((err) => { 15 | console.log(err); 16 | }) 17 | -------------------------------------------------------------------------------- /examples/yandexSmart.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.yandexSmart({ 8 | pageurl: "https://captcha-api.yandex.ru/demo", 9 | sitekey: "FEXfAbHQsToo97VidNVk3j4dC74nGW1DgdxjtNB9" 10 | }) 11 | .then((res) => { 12 | console.log(res); 13 | }) 14 | .catch((err) => { 15 | console.log(err); 16 | }) 17 | -------------------------------------------------------------------------------- /examples/recaptcha_v2.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.recaptcha({ 8 | pageurl: 'https://solvecaptcha.com/demo/recaptcha-v2', 9 | googlekey: '6LfD3PIbAAAAAJs_eEHvoOl75_83eXSqpPSRFJ_u' 10 | }) 11 | .then((res) => { 12 | console.log(res); 13 | }) 14 | .catch((err) => { 15 | console.log(err); 16 | }) 17 | -------------------------------------------------------------------------------- /examples/friendlyCaptcha.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.friendlyCaptcha({ 8 | pageurl: "https://geizhals.de/?liftban=1&from=/455973138?fsean=5901747021356", 9 | sitekey: "FCMST5VUMCBOCGQ9" 10 | }) 11 | .then((res) => { 12 | console.log(res); 13 | }) 14 | .catch((err) => { 15 | console.log(err); 16 | }) 17 | -------------------------------------------------------------------------------- /examples/cutcaptcha.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.cutCaptcha({ 8 | pageurl: "https://mysite.com/page/with/cutcaptcha", 9 | miseryKey: "098e6a849af406142e3150dbf4e6d0538db2b51f", 10 | apiKey: "SAs61IAI", 11 | }) 12 | .then((res) => { 13 | console.log(res); 14 | }) 15 | .catch((err) => { 16 | console.log(err); 17 | }) 18 | -------------------------------------------------------------------------------- /examples/atbcaptcha.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.atbCaptcha({ 8 | pageurl: "https://mysite.com/page/with/atbCAPTCHA", 9 | appId: "af25e409b33d722a95e56a230ff8771c", 10 | apiServer: "https://cap.aisecurius.com" 11 | }) 12 | .then((res) => { 13 | console.log(res); 14 | }) 15 | .catch((err) => { 16 | console.log(err); 17 | }) 18 | -------------------------------------------------------------------------------- /examples/audio.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | const fs = require('fs') 8 | const audioCaptchaBase64 = fs.readFileSync("./media/example.mp3", "base64") 9 | 10 | solver.audio({ 11 | body: audioCaptchaBase64, 12 | lang: 'en' 13 | }) 14 | .then((res) => { 15 | console.log(res); 16 | }) 17 | .catch((err) => { 18 | console.log(err); 19 | }) 20 | -------------------------------------------------------------------------------- /examples/funcaptcha.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.funCaptcha({ 8 | pageurl: "https://api.funcaptcha.com/fc/api/nojs/?pkey=69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC", 9 | publickey: "69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC", 10 | data: '{"blob": "foo"}' 11 | }) 12 | .then((res) => { 13 | console.log(res); 14 | }) 15 | .catch((err) => { 16 | console.log(err); 17 | }) 18 | -------------------------------------------------------------------------------- /examples/lemin.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.lemin({ 8 | pageurl:'https://solvecaptcha.com/demo/lemin', 9 | captcha_id: 'CROPPED_3dfdd5c_d1872b526b794d83ba3b365eb15a200b', 10 | div_id: 'lemin-cropped-captcha', 11 | api_server: 'api.leminnow.com' 12 | }) 13 | .then((res) => { 14 | console.log(res); 15 | }) 16 | .catch((err) => { 17 | console.log(err); 18 | }) 19 | -------------------------------------------------------------------------------- /examples/balance.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | /** 8 | * This example demonstrates how to retrieve the current `balance` of an API key 9 | * in the solvecaptcha.com system using the `balance()` method from the `Solver` class. 10 | */ 11 | solver.balance() 12 | .then((res) => { 13 | console.log(res); 14 | }) 15 | .catch((err) => { 16 | console.log(err); 17 | }) 18 | -------------------------------------------------------------------------------- /examples/coordinates.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | const fs = require('fs') 8 | const imageBase64 = fs.readFileSync("./media/coordinates.jpg", "base64") 9 | 10 | solver.coordinates({ 11 | body: imageBase64, 12 | textinstructions: 'Select all photos containing the boat' 13 | }) 14 | .then((res) => { 15 | console.log(res); 16 | }) 17 | .catch((err) => { 18 | console.log(err); 19 | }) 20 | -------------------------------------------------------------------------------- /examples/recaptcha_v3.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.recaptcha({ 8 | pageurl: 'https://solvecaptcha.com/demo/recaptcha-v3', 9 | googlekey: '6Lcyqq8oAAAAAJE7eVJ3aZp_hnJcI6LgGdYD8lge', 10 | version: "v3", 11 | min_score: "0.4", 12 | action: 'demo_action' 13 | }) 14 | .then((res) => { 15 | console.log(res); 16 | }) 17 | .catch((err) => { 18 | console.log(err); 19 | }) 20 | -------------------------------------------------------------------------------- /examples/rotate.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | const fs = require('fs') 8 | const imageBase64 = fs.readFileSync("./media/rotatecaptcha.png", "base64") 9 | 10 | solver.rotate({ 11 | body: imageBase64, 12 | angle: 15, 13 | textinstructions: "Rotate the object to the correct position" 14 | }) 15 | .then((res) => { 16 | console.log(res); 17 | }) 18 | .catch((err) => { 19 | console.log(err); 20 | }) 21 | -------------------------------------------------------------------------------- /examples/cyberSiARA.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.cyberSiARA({ 8 | pageurl: "https://www.cybersiara.com/book-a-demo", 9 | master_url_id: "OXR2LVNvCuXykkZbB8KZIfh162sNT8S2", 10 | userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" 11 | }) 12 | .then((res) => { 13 | console.log(res); 14 | }) 15 | .catch((err) => { 16 | console.log(err); 17 | }) 18 | -------------------------------------------------------------------------------- /examples/keyCaptcha.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | solver.keyCaptcha({ 8 | pageurl: "https://solvecaptcha.com/demo/keycaptcha", 9 | userId: '184015', 10 | sessionId: '0917788cad24ad3a69813c4fcd556061', 11 | webServerSign: '02f7f9669f1269595c4c69bcd4a3c52e', 12 | webServerSign2: 'd888700f6f324ec0f32b44c32c50bde1' 13 | }) 14 | .then((res) => { 15 | console.log(res); 16 | }) 17 | .catch((err) => { 18 | console.log(err); 19 | }) 20 | -------------------------------------------------------------------------------- /examples/imageCaptcha.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | const fs = require('fs') 8 | const imageBase64 = fs.readFileSync("./media/imageCaptcha_6e584.png", "base64") 9 | 10 | solver.imageCaptcha({ 11 | body: imageBase64, 12 | numeric: 4, 13 | min_len: 5, 14 | max_len: 5, 15 | lang: 'en', 16 | textinstructions: 'Type text on the image' 17 | }) 18 | .then((res) => { 19 | console.log(res); 20 | }) 21 | .catch((err) => { 22 | console.log(err); 23 | }) 24 | -------------------------------------------------------------------------------- /examples/canvas.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | const fs = require('fs') 8 | const imageBase64 = fs.readFileSync("./media/canvas.png", "base64") 9 | const imginstructionsBase64 = fs.readFileSync("./media/canvasImgInstructions.jpg", "base64") 10 | 11 | solver.canvas({ 12 | body: imageBase64, 13 | textinstructions: 'Highlight the red CIRCLE', 14 | imginstructions: imginstructionsBase64, 15 | }) 16 | .then((res) => { 17 | console.log(res); 18 | }) 19 | .catch((err) => { 20 | console.log(err); 21 | }) 22 | -------------------------------------------------------------------------------- /src/structs/providers/providers.ts: -------------------------------------------------------------------------------- 1 | import { supportedProviders } from "../constants/constants"; 2 | 3 | const defautlProvider = supportedProviders.solveCaptcha.name 4 | 5 | export default function getProviderData( provider = defautlProvider ) { 6 | 7 | const currentProvider = provider 8 | let currentProviderData 9 | 10 | switch(currentProvider){ 11 | case 'solvecaptcha': 12 | currentProviderData = supportedProviders.solveCaptcha 13 | break; 14 | // case 'opencaptcha': 15 | // currentProviderData = supportedProviders.opencaptcha 16 | // break; 17 | default: 18 | currentProviderData = supportedProviders.solveCaptcha 19 | } 20 | 21 | return currentProviderData 22 | } -------------------------------------------------------------------------------- /examples/grid.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | const fs = require('fs') 8 | const imageBase64 = fs.readFileSync("./media/recaptchaGrid4x4.jpg", "base64") 9 | const instructionsImageBase64 = fs.readFileSync("./media/recaptchaGridImginstructions4x4.jpg", "base64") 10 | 11 | solver.grid({ 12 | body: imageBase64, 13 | textinstructions: "Select all squares with stairs", 14 | imginstructions: instructionsImageBase64, 15 | cols: 4, 16 | rows: 4 17 | }) 18 | .then((res) => { 19 | console.log(res); 20 | }) 21 | .catch((err) => { 22 | console.log(err); 23 | }) 24 | -------------------------------------------------------------------------------- /examples/boundingBox.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | const fs = require('fs'); 8 | const imageBase64 = fs.readFileSync("./media/boundingBox.jpg", "base64") 9 | const imageInstructionsBase64 = fs.readFileSync("./media/boundingBoxImginstructions.jpg", "base64") 10 | 11 | solver.boundingBox({ 12 | image: imageBase64, 13 | // important, be sure to convey instructions to employees in the form of "imginstructions" or "textinstructions" 14 | imginstructions: imageInstructionsBase64, 15 | textinstructions: "Circle all the cars in the image.", 16 | }) 17 | .then((res) => { 18 | console.log(res); 19 | }) 20 | .catch((err) => { 21 | console.log(err); 22 | }) 23 | -------------------------------------------------------------------------------- /examples/dataDome.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | const proxy = process.env.proxy 8 | const proxytype = process.env.proxytype 9 | solver.dataDome({ 10 | pageurl: "https://rendezvousparis.hermes.com/client/register", 11 | captcha_url: "https://geo.captcha-delivery.com/captcha/?initialCid=AHrlqAAAAAMAEuQtkf4k1c0ABZhYZA%3D%3D&hash=789361B674144528D0B7EE76B35826&cid=mY4z7GNmh7Nt1lAFwpbNHAOcWPhyPgjHD2K1Pm~Od1iEKYLUnK3t7N2ZGUj8OqDK65cnwJHtHwd~t902vlwpSBA5l4ZHbS1Qszv~jEuEUJNQ_jMAjar2Kj3kq20MRJYh&t=fe&referer=https%3A%2F%2Frendezvousparis.hermes.com%2Fclient%2Fregister&s=40119&e=67fef144ac1a54dbd7507776367d2f9d5e36ec3add17fa22f3cb881db8385838", 12 | userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", 13 | proxy: proxy, 14 | proxytype: proxytype 15 | }) 16 | .then((res) => { 17 | console.log(res); 18 | }) 19 | .catch((err) => { 20 | console.log(err); 21 | }) 22 | -------------------------------------------------------------------------------- /examples/reports.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | const fs = require('fs') 8 | const imageBase64 = fs.readFileSync("./media/imageCaptcha_6e584.png", "base64") 9 | 10 | /** 11 | * Example of solving a base64 image captcha and sending a report based on the result 12 | */ 13 | solver.imageCaptcha({ 14 | body: imageBase64, 15 | numeric: 4, 16 | min_len: 5, 17 | max_len: 5, 18 | lang: 'en', 19 | textinstructions: 'Type text on the image' 20 | }) 21 | .then((res) => { 22 | console.log(res); 23 | let isCorrectAnswer = res.data === '6e584'; 24 | console.log("Is correct answer: " + isCorrectAnswer); 25 | 26 | if (isCorrectAnswer) { 27 | console.log("Good report:"); 28 | return solver.goodReport(res.id); 29 | } else { 30 | console.log("Bad report:"); 31 | return solver.badReport(res.id); 32 | } 33 | }) 34 | .catch((err) => { 35 | console.log(err); 36 | }) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Solvecaptcha 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /examples/amazonWaf.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | //INFO: The `context` value is dynamic, it is necessary to take the actual value from the page each time. 8 | solver.amazonWaf({ 9 | pageurl: "https://non-existent-example.execute-api.us-east-1.amazonaws.com/latest", 10 | sitekey: "AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AHMDLodoefdvyOnsHMRtEKQAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMUX+ZqwwuANRnZujSAgEQgDvHSxUQmVBuyUtumoW2n4ccTG7xQN1r3X/zz41qmQaYv9SSSvQrjIoDXKaUQ23tVb4ii8+uljuRdz/HPA==", 11 | context: "9BUgmlm48F92WUoqv97a49ZuEJJ50TCk9MVr3C7WMtQ0X6flVbufM4n8mjFLmbLVAPgaQ1Jydeaja94iAS49ljb+sUNLoukWedAQZKrlY4RdbOOzvcFqmD/ZepQFS9N5w15Exr4VwnVq+HIxTsDJwRviElWCdzKDebN/mk8/eX2n7qJi5G3Riq0tdQw9+C4diFZU5E97RSeahejOAAJTDqduqW6uLw9NsjJBkDRBlRjxjn5CaMMo5pYOxYbGrM8Un1JH5DMOLeXbq1xWbC17YSEoM1cRFfTgOoc+VpCe36Ai9Kc=", 12 | iv: "CgAHbCe2GgAAAAAj", 13 | }) 14 | .then((res) => { 15 | console.log(res); 16 | }) 17 | .catch((err) => { 18 | console.log(err); 19 | }) 20 | -------------------------------------------------------------------------------- /examples/grid_options.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | const fs = require("fs"); 8 | const imageBase64 = fs.readFileSync("./media/recaptchaGrid4x4.jpg", "base64"); 9 | const imageInstructionsBase64 = fs.readFileSync("./media/recaptchaGridImginstructions4x4.jpg", "base64"); 10 | 11 | solver.grid({ 12 | body: imageBase64, 13 | textinstructions: "select all squares with stairs if there are none, click skip", 14 | imginstructions: imageInstructionsBase64, 15 | cols: 4, 16 | rows: 4, 17 | minClicks: 2, 18 | maxClicks: 6, 19 | lang: "en", 20 | canSkip: 1, 21 | imgType: "recaptcha" /* More information about the `img_type` parameter can be found at: https://solvecaptcha.com/solvecaptcha-api#grid */ 22 | // pingback: '123.123.123.123' /* More info about pingback https://solvecaptcha.com/setting/pingback */ 23 | // previousId: '123456789' 24 | }) 25 | .then((res) => { 26 | console.log(res); 27 | }) 28 | .catch((err) => { 29 | console.log(err); 30 | }); 31 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Package 2 | 3 | on: 4 | # Trigger workflow when a tag starting with 'v' is pushed (e.g., v1.0.0) 5 | push: 6 | tags: 7 | - 'v*.*.*' 8 | 9 | jobs: 10 | publish: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | # Step 1: Check out the repository code 15 | - name: Checkout repository 16 | uses: actions/checkout@v3 17 | 18 | # Step 2: Set up the Node.js environment 19 | - name: Setup Node.js environment 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: '18' # Specify Node.js version (change if needed) 23 | registry-url: 'https://registry.npmjs.org/' # Set the registry URL for npm 24 | 25 | # Step 3: Install project dependencies 26 | - name: Install dependencies 27 | run: npm ci 28 | 29 | # Step 4: Build the project (compile TypeScript or run your build script) 30 | - name: Build project 31 | run: npm run build 32 | 33 | # Step 5: Run tests to ensure the package works correctly before publishing 34 | # name: Run tests 35 | # run: npm test 36 | 37 | # Step 6: Publish the package to npm using the provided token 38 | - name: Publish package to npm 39 | run: npm publish 40 | env: 41 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # Use the secret stored in GitHub repo secrets 42 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | # Releasing New Package Version 2 | 3 | This document outlines the steps required to release a new version of the package on npm using GitHub Actions for automated publishing. 4 | 5 | ## Prerequisites 6 | 7 | - You have a local clone of the repository. 8 | - Your `package.json` file is properly configured with a unique package name. 9 | - An npm token is added to GitHub Secrets as `NPM_TOKEN`. 10 | - A GitHub Actions workflow file (e.g., `.github/workflows/publish.yml`) is configured to publish the package on tag push. 11 | - All changes are thoroughly tested. 12 | 13 | ## Step 1: Build and Test the Project 14 | 15 | 1. **Build the project:** 16 | 17 | If your build script is defined as: 18 | 19 | `npm run build` 20 | 21 | Currently project don't have tests, you can run [examples](./examples) files for make sure that project work correcly. 22 | 23 | 24 | ## Step 2: Update the Package Version 25 | 26 | 1. **Bump the package version:** 27 | 28 | For a patch update, run: 29 | 30 | `npm version patch` 31 | 32 | or 33 | 34 | `npm version minor` / `npm version major` as needed. 35 | 36 | This command updates the version in package.json, creates a commit, and generates a new tag (e.g., `v0.0.2`). 37 | 38 | 2. **Push Changes:** 39 | 40 | Execute `git push origin master --tags` 41 | 42 | Automated Publishing: The GitHub Actions workflow will automatically build, test, and publish your package to npm. 43 | 44 | -------------------------------------------------------------------------------- /src/utils/renameParams.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * ### Renaming captcha parameters 4 | * 5 | * Description: parameter names used in the API may differ from those used in the library, in such cases parameter names are renamed in accordance with those used in the API. 6 | * 7 | * @param params - captcha parameters as an object 8 | * @returns returns new object with renamed params 9 | * 10 | */ 11 | export default function renameParams(params: any) { 12 | let newParams: any = new Object(); 13 | 14 | /** 15 | * Captcha parameters that need to be renamed before sent to the API. 16 | */ 17 | const replaceParams: any = { 18 | // Grid 19 | "cols" : "recaptchacols", 20 | "rows" : "recaptcharows", 21 | "minClicks" : "min_clicks", 22 | "maxClicks" : "max_clicks", 23 | "canSkip" : "can_no_answer", 24 | "previousId" : "previousID", 25 | "imgType" : "img_type", 26 | 27 | // KeyCaptcha 28 | "userId" : "s_s_c_user_id", 29 | "sessionId":"s_s_c_session_id", 30 | "webServerSign":"s_s_c_web_server_sign", 31 | "webServerSign2":"s_s_c_web_server_sign2", 32 | 33 | // Cutcaptcha 34 | "miseryKey":"misery_key", 35 | "apiKey":"api_key", 36 | 37 | // Tencent 38 | "appId": "app_id", 39 | 40 | // atbCAPTCHA 41 | "apiServer": "api_server", 42 | } 43 | 44 | for(let key in params) { 45 | if(replaceParams.hasOwnProperty(key)) { 46 | newParams[replaceParams[key]] = params[key] 47 | } else { 48 | newParams[key] = params[key] 49 | } 50 | } 51 | 52 | return newParams 53 | } -------------------------------------------------------------------------------- /src/utils/generic.ts: -------------------------------------------------------------------------------- 1 | import FormData from "form-data"; 2 | 3 | 4 | export function toFormData(payload: Record): FormData { 5 | const form = new FormData(); 6 | for (const key in payload) { 7 | if (payload[key] !== undefined) { 8 | form.append(key, payload[key]); 9 | } 10 | } 11 | return form; 12 | } 13 | 14 | 15 | /* 16 | A file fill of generic utility functions. 17 | */ 18 | 19 | /** 20 | * Changes 0 and 1 falsy/truthy values into a boolean. 21 | * @private 22 | * @param input boolean or number 23 | */ 24 | export function castBool(input: boolean | number): 0 | 1 { 25 | if (input == false) return 0 26 | if (input == true) return 1 27 | if (input != 0 && input != 1) return 0 28 | else return input 29 | } 30 | 31 | /** 32 | * Constructs uri parameters from an object 33 | * @private 34 | * @param input The input object 35 | */ 36 | export function objectToURI(input: {[key: string]: string | number | boolean} | any): string { 37 | let res = "?" 38 | const keys = Object.keys(input) 39 | keys.forEach((key, index) => { 40 | res += encodeURIComponent(key) + "=" + encodeURIComponent(input[key]) 41 | if (index + 1 != keys.length) res += "&" 42 | }) 43 | return res 44 | } 45 | 46 | /** 47 | * Returns a promise that resolves after x ms 48 | * @private 49 | * @param ms time to sleep for 50 | */ 51 | export function sleep(ms: number) { 52 | return new Promise((resolve) => setTimeout(resolve, ms)) 53 | } -------------------------------------------------------------------------------- /examples/geetest.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: '../.env' }); 2 | const { Solver } = require('../dist/index.js'); 3 | 4 | const APIKEY = process.env.SOLVECAPTCHA_APIKEY; 5 | const solver = new Solver(APIKEY); 6 | 7 | const fetch = require('node-fetch'); 8 | (async () => { 9 | /** 10 | * Warning: Attention, the `challenge` value is not static but dynamic. 11 | * You need to find the queries that makes the captcha on the page to API. 12 | * Then you need to make request to this API and get new `challenge`. 13 | * 14 | * For page https://solvecaptcha.com/demo/geetest, api address is https://solvecaptcha.com/api/v1/captcha-demo/gee-test/init-params?t=${t} 15 | * Also note that when make request to API, the request uses the dynamic parameter `t` 16 | * 17 | * You can read more about sending GeeTest here https://solvecaptcha.com/solvecaptcha-api#solving_geetest, or here https://solvecaptcha.com/p/geetest 18 | * In this example you can see how to solve GeeTest on the page https://solvecaptcha.com/demo/geetest 19 | * 20 | */ 21 | 22 | const t = new Date().getTime() 23 | // below is a request to get a new `challenge`. 24 | const response = await fetch(`https://solvecaptcha.com/api/v1/captcha-demo/gee-test/init-params?t=${t}`) 25 | const data = await response.json() 26 | 27 | const params = { 28 | pageurl: 'https://solvecaptcha.com/demo/geetest', 29 | gt: data.gt, 30 | challenge: data.challenge 31 | } 32 | 33 | const res = await solver.geetest(params) 34 | try { 35 | console.log(res) 36 | } catch (error) { 37 | console.error(error); 38 | } 39 | })() 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solvecaptcha-javascript", 3 | "version": "1.0.1", 4 | "description": "Node.js wrapper for SolveCaptcha.com API. Bypass recaptcha, cloudflare capthca and more.", 5 | "main": "dist/index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/solvercaptcha/solvecaptcha-javascript.git" 9 | }, 10 | "license": "MIT", 11 | "author": "Solvecaptcha", 12 | "bugs": { 13 | "url": "hhttps://github.com/solvercaptcha/solvecaptcha-javascript/issues" 14 | }, 15 | "homepage": "https://github.com/solvercaptcha/solvecaptcha-javascript", 16 | "types": "dist/index.d.ts", 17 | "keywords": [ 18 | "solvecaptcha", 19 | "reCAPTCHA", 20 | "FunCaptcha", 21 | "Cloudflare Turnstile", 22 | "captcha", 23 | "api", 24 | "captchasolver", 25 | "capmonster", 26 | "Geetest", 27 | "image captcha", 28 | "Coordinates", 29 | "Click Captcha", 30 | "Geetest V4", 31 | "Yandex Smart Captcha", 32 | "Lemin captcha", 33 | "bypass captcha", 34 | "solve captcha", 35 | "Amazon WAF", 36 | "Capy Puzzle", 37 | "DataDome CAPTCHA", 38 | "CyberSiARA", 39 | "MTCaptcha", 40 | "Bounding Box Method", 41 | "Friendly Captcha", 42 | "Text Captcha", 43 | "Canvas", 44 | "Rotate", 45 | "KeyCaptcha", 46 | "Cutcaptcha", 47 | "Tencent", 48 | "atbCAPTCHA", 49 | "Audio Recognition" 50 | ], 51 | "scripts": { 52 | "build": "tsc && node ./dist/index.js", 53 | "compile": "tsc", 54 | "jsdoc": "jsdoc", 55 | "docgen": "tsc && yarn jsdoc ./dist -R \"./readme.md\" -P \"./package.json\" -t \"./node_modules/jaguarjs-jsdoc\" -d \"./docs\" -r", 56 | "example": "tsc && node ./tests/mtCaptcha.js" 57 | }, 58 | "dependencies": { 59 | "@types/node-fetch": "^2.6.12", 60 | "form-data": "^4.0.2", 61 | "node-fetch": "^2.7.0", 62 | "undici": "^6.0.0" 63 | }, 64 | "devDependencies": { 65 | "@types/node": "^20.8.7", 66 | "dotenv": "^16.0.3", 67 | "jaguarjs-jsdoc": "^1.0.2", 68 | "jsdoc": "^4.0.2", 69 | "typescript": "^4.9.4" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and maintainers pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. 8 | 9 | ## Our Standards 10 | 11 | Examples of behavior that contributes to creating a positive environment include: 12 | 13 | - Using welcoming and inclusive language 14 | - Being respectful of differing viewpoints and experiences 15 | - Gracefully accepting constructive criticism 16 | - Focusing on what is best for the community 17 | - Showing empathy toward other community members 18 | 19 | Examples of unacceptable behavior by participants include: 20 | 21 | - The use of sexualized language or imagery and unwelcome sexual attention or advances 22 | - Trolling, insulting/derogatory comments, and personal or political attacks 23 | - Public or private harassment 24 | - Publishing others' private information, such as a physical or email address, without their explicit permission 25 | - Other conduct which could reasonably be considered inappropriate in a professional setting 26 | 27 | ## Our Responsibilities 28 | 29 | Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any instances of unacceptable behavior. 30 | 31 | Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 32 | 33 | ## Scope 34 | 35 | This Code of Conduct applies within all project spaces, both public and private, when an individual is representing the project or its community in any way. 36 | 37 | Examples of representing a project or community include using an official project email address, posting via an official social media account, or acting as an appointed representative at an online or offline event. 38 | 39 | ## Enforcement 40 | 41 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at info@solvecaptcha.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. 42 | 43 | If you have any questions or suggestions about this Code of Conduct, feel free to reach out to the project team. 44 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to solvecaptcha-javascript 2 | 3 | Thank you for considering contributing to the solvecaptcha-javascript! By contributing, you're helping improve the project and enabling others to benefit from your improvements. 4 | 5 | Here are a few guidelines to help you get started. 6 | 7 | ## How to Contribute 8 | 9 | 1. **Fork the repository** 10 | If you'd like to contribute, please start by forking the project and cloning it to your local machine. 11 | 12 | ```bash 13 | git clone https://github.com/solvercaptcha/solvecaptcha-javascript.git 14 | ``` 15 | 16 | 2. **Create a new branch** 17 | Create a new branch for your feature or bug fix. This will help keep your changes separate from the main codebase. 18 | 19 | ```bash 20 | git checkout -b my-feature-branch 21 | ``` 22 | 23 | 3. **Make your changes** 24 | Modify the code or documentation as needed. Make sure to follow the project's coding style and conventions. 25 | 26 | 4. **Test your changes** 27 | Ensure that your changes work as expected and do not break anything in the project. If applicable, write tests to cover your changes. 28 | 29 | 5. **Commit your changes** 30 | After you've made your changes, commit them with a meaningful message describing what you've done. 31 | 32 | ```bash 33 | git commit -m "Add feature X to bypass challenge" 34 | ``` 35 | 36 | 6. **Push your changes** 37 | Push your changes to your forked repository. 38 | 39 | ```bash 40 | git push origin my-feature-branch 41 | ``` 42 | 43 | 7. **Submit a pull request** 44 | Navigate to the original repository and submit a pull request. Describe the changes you've made and why they're important. 45 | 46 | We will review your pull request and get back to you as soon as possible! 47 | 48 | ## Reporting Issues 49 | 50 | If you find any bugs or issues with the project, feel free to open an issue in the **Issues** tab. When reporting an issue, please provide the following information: 51 | 52 | - A detailed description of the issue. 53 | - Steps to reproduce the issue. 54 | - Any relevant error messages or logs. 55 | 56 | ## Code of Conduct 57 | 58 | By contributing to this project, you agree to abide by our [Code of Conduct](./CODE_OF_CONDUCT.md). Please be respectful and considerate to other contributors. 59 | 60 | ## Types of Contributions 61 | 62 | Here are some ways you can contribute to the project: 63 | 64 | - **Bug Fixes**: If you find a bug, feel free to submit a pull request with a fix. 65 | - **Feature Requests**: Have a great idea for a new feature? Open an issue to discuss it! 66 | - **Documentation**: Help improve the documentation or add new guides to make the project more accessible to others. 67 | - **Tests**: Ensure that the project is thoroughly tested and improve the test coverage. 68 | - **Code Refactoring**: Help improve the project codebase by refactoring or optimizing the code. 69 | 70 | ## Thank You! 71 | 72 | Your contributions are greatly appreciated! Together, we can make this project even better for everyone. 73 | -------------------------------------------------------------------------------- /src/structs/solvecaptchaServer.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from "events"; 2 | import { paramsRecaptcha } from "./solvecaptcha.js"; 3 | 4 | // For creating the server 5 | import * as http from "http"; 6 | 7 | export interface ServerCaptchaResult { 8 | data: string, 9 | id: string 10 | } 11 | 12 | export interface ServerEvents { 13 | "recaptcha": (captcha: ServerCaptchaResult) => void; 14 | } 15 | 16 | export interface Server { 17 | on( 18 | event: U, listener: ServerEvents[U] 19 | ): this; 20 | } 21 | 22 | /** 23 | * ! WIP 24 | * This class will bind an http server to a specific port to allow for post requests from the solvecaptcha site, providing 25 | * an alternative to manually polling each captcha. A feature solvecaptcha allows for massive solve requirements. 26 | */ 27 | export class Server extends EventEmitter { 28 | private _apikey: string; 29 | private _headerACAO: number; 30 | 31 | private _serverAddr: string; 32 | private _serverPort: number; 33 | private _pingbackString: string; 34 | 35 | private _terminated: boolean = false; 36 | 37 | constructor(apikey: string, serverAddr: string, serverPort: number, pingbackString: string, enableACAO: boolean = true) { 38 | super(); 39 | this._apikey = apikey; 40 | this._headerACAO = enableACAO ? 1 : 0; 41 | this._serverAddr = serverAddr; 42 | this._serverPort = serverPort 43 | this._pingbackString = pingbackString; 44 | 45 | this.server(); 46 | } 47 | 48 | private async server() { 49 | const server = http.createServer((req, res) => { 50 | if (req.method == "POST") { 51 | let body = ''; 52 | req.on('data', chunk => { 53 | body += chunk.toString(); // convert Buffer to string 54 | }); 55 | req.on('end', () => { 56 | console.log(body); 57 | res.end('ok'); 58 | }); 59 | } 60 | 61 | if (req.method == "GET" && req.url == "/solvecaptcha.txt") { 62 | console.log("writing") 63 | res.write(this._pingbackString, "utf8") 64 | res.end(); 65 | } 66 | }) 67 | 68 | server.listen(this._serverPort); 69 | 70 | // let i = setInterval(() => { 71 | // if (this._terminated == true) { 72 | // clearInterval(i); 73 | // server.close(); 74 | // } 75 | // }, 100) 76 | } 77 | 78 | private get defaultPayload() { 79 | return { 80 | key: this._apikey, json: 1, header_acao: this._headerACAO, soft_id: 4845 81 | } 82 | } 83 | 84 | /** 85 | * Termintes the running HTTP server. 86 | */ 87 | public terminate() { 88 | this._terminated = true; 89 | } 90 | requestRecaptcha(params: paramsRecaptcha) { 91 | const payload = { 92 | ...params, 93 | method: "userrecaptcha", 94 | ...this.defaultPayload 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | // "incremental": true, /* Enable incremental compilation */ 5 | "target": "es2019", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ 6 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 7 | // "lib": [], /* Specify library files to be included in the compilation. */ 8 | // "allowJs": false, /* Allow javascript files to be compiled. */ 9 | // "checkJs": true, /* Report errors in .js files. */ 10 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 11 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 12 | "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 13 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 14 | // "outFile": "./", /* Concatenate and emit output to single file. */ 15 | "outDir": "./dist", /* Redirect output structure to the directory. */ 16 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 17 | // "composite": true, /* Enable project compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | "removeComments": false, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true, /* Enable all strict type-checking options. */ 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | // "strictNullChecks": true, /* Enable strict null checks. */ 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | 41 | /* Module Resolution Options */ 42 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 43 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 44 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 45 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 46 | // "typeRoots": [], /* List of folders to include type definitions from. */ 47 | // "types": [], /* Type declaration files to be included in compilation. */ 48 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 49 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 50 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 51 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 52 | 53 | /* Source Map Options */ 54 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 55 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 56 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 57 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 58 | 59 | /* Experimental Options */ 60 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 61 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 62 | 63 | /* Advanced Options */ 64 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 65 | }, 66 | "exclude": [ 67 | "examples/*", 68 | "dist/*" 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /src/utils/checkCaptchaParams.ts: -------------------------------------------------------------------------------- 1 | // Captcha methods for which parameter checking is available 2 | const supportedMethods = ["userrecaptcha", "geetest", "geetest_v4","yandex","funcaptcha","lemin","amazon_waf", 3 | "turnstile", "base64", "capy","datadome", "cybersiara", "mt_captcha", "bounding_box", 'friendly_captcha', 'grid', 4 | 'textcaptcha', 'canvas', 'rotatecaptcha', 'keycaptcha', 'cutcaptcha', 'tencent', 'atb_captcha', 'audio'] 5 | 6 | // Names of required fields that must be contained in the parameters captcha 7 | const recaptchaRequiredFields = ['pageurl','googlekey'] 8 | const geetestRequiredFields = ['pageurl','gt','challenge'] 9 | const geetestV4RequiredFields = ['pageurl','captcha_id'] 10 | const yandexSmartRequiredFields = ['pageurl','sitekey'] 11 | const funCaptchaRequiredFields = ['pageurl','publickey'] 12 | const leminRequiredFields = ['pageurl','div_id','captcha_id'] 13 | const amazonWafRequiredFields = ['pageurl','context','iv','sitekey'] 14 | const turnstileRequiredFields = ['pageurl','sitekey'] 15 | // `base64RequiredFields` for Normal Captcha and Coordinates captcha 16 | const base64RequiredFields = ['body'] 17 | const capyPuzzleRequiredFields = ['captchakey'] 18 | const dataDomeRequiredFields = ['pageurl', 'captcha_url', 'userAgent', 'proxy', 'proxytype'] 19 | const cyberSiARARequiredFields = ['pageurl', 'master_url_id', 'userAgent'] 20 | const mtCaptchaRequiredFields = ['pageurl', 'sitekey'] 21 | const boundingBoxRequiredFields = ['image'] // and textinstructions or imginstructions 22 | const friendlyCaptchaFields = ['pageurl','sitekey'] 23 | const gridRequiredFields = ['body'] // and textinstructions or imginstructions 24 | const textCaptchaRequiredFields = ['textcaptcha'] 25 | const canvasRequiredFields = ['body'] // and textinstructions or imginstructions 26 | const rotateRequiredFields = ['body'] 27 | const keycaptchaRequiredFields = ['pageurl', 's_s_c_user_id', 's_s_c_session_id', 's_s_c_web_server_sign', 's_s_c_web_server_sign2'] 28 | const cutcaptchaRequiredFields = ['pageurl', 'misery_key', 'api_key'] 29 | const tencentRequiredFields = ['pageurl', 'app_id'] 30 | const atbCaptchaRequiredFields = ['pageurl', 'app_id', 'api_server'] 31 | const audioRequiredFields = ['body', 'lang'] 32 | 33 | /** 34 | * Getting required arguments for a captcha. 35 | * 36 | * @param {string} method method for solving captcha. 37 | * @returns {Array} An array containing the required arguments for this captcha 38 | */ 39 | const getRequiredFildsArr = (method: string):Array => { 40 | let requiredFieldsArr = ['pageurl'] 41 | 42 | switch(method){ 43 | case "userrecaptcha": 44 | requiredFieldsArr = recaptchaRequiredFields 45 | break; 46 | case "geetest": 47 | requiredFieldsArr = geetestRequiredFields 48 | break; 49 | case "geetest_v4": 50 | requiredFieldsArr = geetestV4RequiredFields 51 | break; 52 | case "yandex": 53 | requiredFieldsArr = yandexSmartRequiredFields 54 | break; 55 | case "funcaptcha": 56 | requiredFieldsArr = funCaptchaRequiredFields 57 | break; 58 | case "lemin": 59 | requiredFieldsArr = leminRequiredFields 60 | break; 61 | case "amazon_waf": 62 | requiredFieldsArr = amazonWafRequiredFields 63 | break; 64 | case "turnstile": 65 | requiredFieldsArr = turnstileRequiredFields 66 | break; 67 | case "base64": 68 | requiredFieldsArr = base64RequiredFields 69 | break; 70 | case "grid": 71 | requiredFieldsArr = gridRequiredFields 72 | break; 73 | case "capy": 74 | requiredFieldsArr = capyPuzzleRequiredFields 75 | break; 76 | case "datadome": 77 | requiredFieldsArr = dataDomeRequiredFields 78 | break; 79 | case "cybersiara": 80 | requiredFieldsArr = cyberSiARARequiredFields 81 | break; 82 | case "mt_captcha": 83 | requiredFieldsArr = mtCaptchaRequiredFields 84 | break; 85 | case "bounding_box": 86 | requiredFieldsArr = boundingBoxRequiredFields 87 | break; 88 | case "friendly_captcha": 89 | requiredFieldsArr = friendlyCaptchaFields 90 | break; 91 | case "textcaptcha": 92 | requiredFieldsArr = textCaptchaRequiredFields 93 | break; 94 | case "canvas": 95 | requiredFieldsArr = canvasRequiredFields 96 | break; 97 | case "rotatecaptcha": 98 | requiredFieldsArr = rotateRequiredFields 99 | break; 100 | case "keycaptcha": 101 | requiredFieldsArr = keycaptchaRequiredFields 102 | break; 103 | case "cutcaptcha": 104 | requiredFieldsArr = cutcaptchaRequiredFields 105 | break; 106 | case "tencent": 107 | requiredFieldsArr = tencentRequiredFields 108 | break; 109 | case "atb_captcha": 110 | requiredFieldsArr = atbCaptchaRequiredFields 111 | break; 112 | case "audio": 113 | requiredFieldsArr = audioRequiredFields 114 | break; 115 | } 116 | return requiredFieldsArr 117 | } 118 | 119 | /** 120 | * ### Captcha Required Parameters Check. 121 | * 122 | * Checking required captcha parameters before sending. 123 | * This function checks for required fields in the provided captcha parameters. 124 | * Throws an error if the specified method is not supported or if required fields are missing. 125 | * 126 | * Note: The `checkCaptchaParams()` function should be called after `renameParams()`, if function `renameParams()` is used. 127 | * 128 | * @param { Object } params Captcha parameters that need to be checked. 129 | * @returns true | false | Error 130 | * @example 131 | * checkCaptchaParams(params, 'userrecaptcha') 132 | */ 133 | export default function checkCaptchaParams(params: Object, method: string) { 134 | let isCorrectCaptchaParams 135 | const isIncorrectCaptchaMethod = !supportedMethods.includes(method) 136 | 137 | if(isIncorrectCaptchaMethod) { 138 | isCorrectCaptchaParams = false 139 | throw new Error(`Error when check params captcha. \nNot found "${method}" method in the "supportedMethods" array. \nCheck if the method is written correctly `) 140 | } 141 | 142 | const requiredFields = getRequiredFildsArr(method) 143 | 144 | requiredFields.forEach(fieldName => { 145 | const isThisFieldNotAvailable = !params.hasOwnProperty(fieldName) 146 | 147 | if(isThisFieldNotAvailable) { 148 | isCorrectCaptchaParams = false 149 | throw new Error(`Error when check params captcha.\nNot found "${fieldName}" field in the Object. Field "${fieldName}" is required for "${method}" method. Please add field "${fieldName}" in object and try again.\nPlease correct your code for the "${method}" method according to the code examples`) 150 | } else { 151 | isCorrectCaptchaParams = true 152 | } 153 | }) 154 | 155 | //The parameters `textinstructions` and `imginstructions` are mandatory for the methods `bounding_box`, `grid`, and `canvas`. 156 | if(method === "bounding_box" || method === "grid" || method === "canvas") { 157 | if(params.hasOwnProperty('textinstructions') || params.hasOwnProperty('imginstructions')) { 158 | isCorrectCaptchaParams = true 159 | } else { 160 | isCorrectCaptchaParams = false 161 | throw new Error(`Error when check params captcha.\nNot found "textinstructions" or "imginstructions" field in the Object. One of this field is required for "${method}" method. Please add field "textinstructions" or "imginstructions" to captcha parameters.`) 162 | } 163 | } 164 | 165 | return isCorrectCaptchaParams 166 | } -------------------------------------------------------------------------------- /src/structs/solvecaptchaError.ts: -------------------------------------------------------------------------------- 1 | export class APIError extends Error { 2 | code: number 3 | constructor(public err: string) { 4 | super(err) 5 | this.name = this.constructor.name 6 | switch (err) { 7 | case "ERROR_CAPTCHA_UNSOLVABLE": { 8 | this.code = 1 9 | this.message = "Your captcha was unable to be solved after 3 attempts. You haven't been charged for this request." 10 | }; break; 11 | case "ERROR_WRONG_USER_KEY": { 12 | this.code = 2 13 | this.message = "You've specified an invalid key, please make sure it is 32 characters long." 14 | }; break; 15 | case "ERROR_KEY_DOES_NOT_EXIST": { 16 | this.code = 3 17 | this.message = "The key you've provided does not exist." 18 | }; break; 19 | case "ERROR_BAD_DUPLICATES": { 20 | this.code = 4 21 | this.message = "The max number of attempts for this captcha has been reached. Please validate." 22 | }; break; 23 | case "REPORT_NOT_RECORDED": { 24 | this.code = 5 25 | this.message = "You have submitted an invalid report. Either you've submitted over 40% of recent captchas, or the captcha was solved over 15 minutes ago." 26 | }; break; 27 | case "ERROR_DUPLICATE_REPORT": { 28 | this.code = 6 29 | this.message = "You have already reported this captcha!" 30 | }; break; 31 | case "ERROR_IMAGE_TYPE_NOT_SUPPORTED": { 32 | this.code = 7 33 | this.message = "The image type is not supported. Please validate it's a valid image you're passing through." 34 | }; break; 35 | case "ERROR_ZERO_CAPTCHA_FILESIZE": { 36 | this.code = 8 37 | this.message = "The image has no size, and is not valid. Please verify it." 38 | }; break; 39 | case "ERROR_ZERO_BALANCE": { 40 | this.code = 9 41 | this.message = "There aren't enough funds in this account to complete the captcha." 42 | }; break; 43 | case "ERROR_PAGEURL": { 44 | this.code = 10 45 | this.message = "pageurl paramter is missing in the request." 46 | }; break; 47 | case "ERROR_NO_SLOT_AVAILABLE": { 48 | this.code = 11 49 | this.message = "Captcha Queue exceeded maximum capacity. Please wait a few moments before continuing, or update your settings at https://solvecaptcha.com/setting" 50 | }; break; 51 | case "ERROR_TOO_BIG_CAPTCHA_FILESIZE": { 52 | this.code = 12 53 | this.message = "The Image Filesize exceeds 100kb. Please check the image file." 54 | }; break; 55 | case "ERROR_WRONG_FILE_EXTENSION": { 56 | this.code = 13 57 | this.message = "Unsupported file extension. Accepted extensions: jpg, jpeg, gif, png." 58 | }; break; 59 | case "ERROR_UPLOAD": { 60 | this.code = 14 61 | this.message = "The Solve Request was malformed. Please make sure the image is valid. If it is, please open up a github issue detailing this event." 62 | }; break; 63 | case "ERROR_IP_NOT_ALLOWED": { 64 | this.code = 15 65 | this.message = "The request is sent from an IP that is not on the allowed list. Please configure it here https://solvecaptcha.com/setting/iplist" 66 | }; break; 67 | case "IP_BANNED": { 68 | this.code = 16 69 | this.message = "This IP address is banned due to frequent attempts to access the server via incorrect auth keys. Please try again in 5 minutes." 70 | }; break; 71 | case "ERROR_BAD_TOKEN_OR_PAGEURL": { 72 | this.code = 17 73 | this.message = "Please insure the googlekey and pageurl are correct for this reCaptcha request." 74 | }; break; 75 | case "ERROR_GOOGLEKEY": { 76 | this.code = 18 77 | this.message = "Please insure the sitekey provided is correct, and try again." 78 | }; break; 79 | case "ERROR_WRONG_GOOGLEKEY": { 80 | this.code = 19 81 | this.message = "The 'googlekey' parameter is missing or of an invalid format. Please make sure it is a valid string." 82 | }; break; 83 | case "ERROR_CAPTCHAIMAGE_BLOCKED": { 84 | this.code = 20 85 | this.message = "You've sent an image that is marked in our database as unrecognizable. Usually that happens if the website where you found the captcha stopped sending you captchas and started to send 'deny access' image." 86 | }; break; 87 | case "TOO_MANY_BAD_IMAGES": { 88 | this.code = 21 89 | this.message = "You're sending too many unrecognizable images. Please make sure the images are valid and understandable." 90 | }; break; 91 | case "MAX_USER_TURN": { 92 | this.code = 22 93 | this.message = "You've made more then 60 requests to in.php within 3 seconds. Please slow down requests, and wait 10 seconds for this restriction to be lifted." 94 | }; break; 95 | case "ERROR_BAD_PARAMETERS": { 96 | this.code = 23 97 | this.message = "Some parameters are missing in this request. If you're using a pre-provided function, please open up an issue on the GitHub" 98 | }; break; 99 | case "ERROR_BAD_PROXY": { 100 | this.code = 24 101 | this.message = "The proxy provided did not work." 102 | }; break; 103 | case "ERROR_CAPTCHA_ID": { 104 | this.code = 250 105 | this.message = "One of the parameters is incorrect. If you are submitting GeeTest V4 captcha, then check that the \'captcha_id\' parameter is correct." 106 | }; break; 107 | 108 | // Start for Res.php errors 109 | case "CAPCHA_NOT_READY": { 110 | this.code = 25 111 | this.message = "The captcha is not solved yet. If you see this error, Please open up an issue on the GitHub" 112 | }; break; 113 | case "ERROR_WRONG_ID_FORMAT": { 114 | this.code = 26 115 | this.message = "You've provided a captcha ID in the wrong format. The ID can contain only numbers." 116 | }; break; 117 | case "ERROR_WRONG_CAPTCHA_ID": { 118 | this.code = 27 119 | this.message = "You've provided an incorrect captcha ID." 120 | }; break; 121 | case "ERROR_BAD_DUPLICATES": { 122 | this.code = 28 123 | this.message = "The number of attempts has been reached, but the minimum number of matches was not hit." 124 | }; break; 125 | case "ERROR_REPORT_NOT_RECORDED": { 126 | this.code = 29 127 | this.message = "You've submitted more then 40% reports, or are reporting a captcha older then 15 minutes. This report has been ignored." 128 | }; break; 129 | case "ERROR_DUPLICATE_REPORT": { 130 | this.code = 30 131 | this.message = "You've already reported this captcha. This report is ignored." 132 | }; break; 133 | case "ERROR_IP_ADDRES": { 134 | this.code = 31 135 | this.message = "The PingBack/CallBack IP did not match the source of this request." 136 | }; break; 137 | case "ERROR_TOKEN_EXPIRED": { 138 | this.code = 32 139 | this.message = "The 'challenge' value for the GeeTest Captcha has already expired." 140 | }; break; 141 | case "ERROR_EMPTY_ACTION": { 142 | this.code = 33 143 | this.message = "The ACtion parameter is missing. Please open an issue in the GitHub" 144 | }; break; 145 | case "ERROR_PROXY_CONNECTION_FAILED": { 146 | this.code = 34 147 | this.message = "The proxy server was unable to load the captcha. This Proxy has been marked as bad, and will recieve an 'ERROR_BAD_PROXY' in future use." 148 | }; break; 149 | case "https://solvecaptcha.com/blog/google-search-recaptcha": { 150 | this.code = 35 151 | this.message = "This captcha appears to be a Google Service Captcha (A special captcha that Google uses to protect their websites). Please provide a 'data-s' attribute in the CaptchaExtras of this function. View https://solvecaptcha.com/blog/google-search-recaptcha for more information." 152 | }; break; 153 | default: { 154 | console.log(err) 155 | this.code = 0 156 | this.message = "An Unexpected Error has occured. Please submit an issue on GitHub detailing this event." 157 | }; 158 | } 159 | } 160 | } -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/parser@^7.20.15": 6 | "integrity" "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==" 7 | "resolved" "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz" 8 | "version" "7.23.0" 9 | 10 | "@jsdoc/salty@^0.2.1": 11 | "integrity" "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==" 12 | "resolved" "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz" 13 | "version" "0.2.5" 14 | dependencies: 15 | "lodash" "^4.17.21" 16 | 17 | "@types/linkify-it@*": 18 | "integrity" "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==" 19 | "resolved" "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz" 20 | "version" "3.0.2" 21 | 22 | "@types/markdown-it@*", "@types/markdown-it@^12.2.3": 23 | "integrity" "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==" 24 | "resolved" "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz" 25 | "version" "12.2.3" 26 | dependencies: 27 | "@types/linkify-it" "*" 28 | "@types/mdurl" "*" 29 | 30 | "@types/mdurl@*": 31 | "integrity" "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==" 32 | "resolved" "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz" 33 | "version" "1.0.2" 34 | 35 | "@types/node-fetch@^2.6.12": 36 | "integrity" "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==" 37 | "resolved" "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz" 38 | "version" "2.6.12" 39 | dependencies: 40 | "@types/node" "*" 41 | "form-data" "^4.0.0" 42 | 43 | "@types/node@*", "@types/node@^20.8.7": 44 | "integrity" "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==" 45 | "resolved" "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz" 46 | "version" "20.8.7" 47 | dependencies: 48 | "undici-types" "~5.25.1" 49 | 50 | "argparse@^2.0.1": 51 | "integrity" "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" 52 | "resolved" "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" 53 | "version" "2.0.1" 54 | 55 | "asynckit@^0.4.0": 56 | "integrity" "sha1-x57Zf380y48robyXkLzDZkdLS3k= sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 57 | "resolved" "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" 58 | "version" "0.4.0" 59 | 60 | "bluebird@^3.7.2": 61 | "integrity" "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 62 | "resolved" "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" 63 | "version" "3.7.2" 64 | 65 | "call-bind-apply-helpers@^1.0.1", "call-bind-apply-helpers@^1.0.2": 66 | "integrity" "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==" 67 | "resolved" "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz" 68 | "version" "1.0.2" 69 | dependencies: 70 | "es-errors" "^1.3.0" 71 | "function-bind" "^1.1.2" 72 | 73 | "catharsis@^0.9.0": 74 | "integrity" "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==" 75 | "resolved" "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz" 76 | "version" "0.9.0" 77 | dependencies: 78 | "lodash" "^4.17.15" 79 | 80 | "combined-stream@^1.0.8": 81 | "integrity" "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==" 82 | "resolved" "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" 83 | "version" "1.0.8" 84 | dependencies: 85 | "delayed-stream" "~1.0.0" 86 | 87 | "delayed-stream@~1.0.0": 88 | "integrity" "sha1-3zrhmayt+31ECqrgsp4icrJOxhk= sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" 89 | "resolved" "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" 90 | "version" "1.0.0" 91 | 92 | "dotenv@^16.0.3": 93 | "integrity" "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" 94 | "resolved" "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz" 95 | "version" "16.0.3" 96 | 97 | "dunder-proto@^1.0.1": 98 | "integrity" "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==" 99 | "resolved" "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz" 100 | "version" "1.0.1" 101 | dependencies: 102 | "call-bind-apply-helpers" "^1.0.1" 103 | "es-errors" "^1.3.0" 104 | "gopd" "^1.2.0" 105 | 106 | "entities@~2.1.0": 107 | "integrity" "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==" 108 | "resolved" "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz" 109 | "version" "2.1.0" 110 | 111 | "es-define-property@^1.0.1": 112 | "integrity" "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" 113 | "resolved" "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz" 114 | "version" "1.0.1" 115 | 116 | "es-errors@^1.3.0": 117 | "integrity" "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" 118 | "resolved" "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" 119 | "version" "1.3.0" 120 | 121 | "es-object-atoms@^1.0.0", "es-object-atoms@^1.1.1": 122 | "integrity" "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==" 123 | "resolved" "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz" 124 | "version" "1.1.1" 125 | dependencies: 126 | "es-errors" "^1.3.0" 127 | 128 | "es-set-tostringtag@^2.1.0": 129 | "integrity" "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==" 130 | "resolved" "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz" 131 | "version" "2.1.0" 132 | dependencies: 133 | "es-errors" "^1.3.0" 134 | "get-intrinsic" "^1.2.6" 135 | "has-tostringtag" "^1.0.2" 136 | "hasown" "^2.0.2" 137 | 138 | "escape-string-regexp@^2.0.0": 139 | "integrity" "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" 140 | "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" 141 | "version" "2.0.0" 142 | 143 | "form-data@^4.0.0", "form-data@^4.0.2": 144 | "integrity" "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==" 145 | "resolved" "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz" 146 | "version" "4.0.2" 147 | dependencies: 148 | "asynckit" "^0.4.0" 149 | "combined-stream" "^1.0.8" 150 | "es-set-tostringtag" "^2.1.0" 151 | "mime-types" "^2.1.12" 152 | 153 | "function-bind@^1.1.2": 154 | "integrity" "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" 155 | "resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" 156 | "version" "1.1.2" 157 | 158 | "get-intrinsic@^1.2.6": 159 | "integrity" "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==" 160 | "resolved" "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz" 161 | "version" "1.3.0" 162 | dependencies: 163 | "call-bind-apply-helpers" "^1.0.2" 164 | "es-define-property" "^1.0.1" 165 | "es-errors" "^1.3.0" 166 | "es-object-atoms" "^1.1.1" 167 | "function-bind" "^1.1.2" 168 | "get-proto" "^1.0.1" 169 | "gopd" "^1.2.0" 170 | "has-symbols" "^1.1.0" 171 | "hasown" "^2.0.2" 172 | "math-intrinsics" "^1.1.0" 173 | 174 | "get-proto@^1.0.1": 175 | "integrity" "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==" 176 | "resolved" "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz" 177 | "version" "1.0.1" 178 | dependencies: 179 | "dunder-proto" "^1.0.1" 180 | "es-object-atoms" "^1.0.0" 181 | 182 | "gopd@^1.2.0": 183 | "integrity" "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" 184 | "resolved" "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz" 185 | "version" "1.2.0" 186 | 187 | "graceful-fs@^4.1.9": 188 | "integrity" "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" 189 | "resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" 190 | "version" "4.2.11" 191 | 192 | "has-symbols@^1.0.3", "has-symbols@^1.1.0": 193 | "integrity" "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" 194 | "resolved" "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz" 195 | "version" "1.1.0" 196 | 197 | "has-tostringtag@^1.0.2": 198 | "integrity" "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==" 199 | "resolved" "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz" 200 | "version" "1.0.2" 201 | dependencies: 202 | "has-symbols" "^1.0.3" 203 | 204 | "hasown@^2.0.2": 205 | "integrity" "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==" 206 | "resolved" "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" 207 | "version" "2.0.2" 208 | dependencies: 209 | "function-bind" "^1.1.2" 210 | 211 | "jaguarjs-jsdoc@^1.0.2": 212 | "integrity" "sha512-QipqhisnCHsauPhrayPst/LnLsvbpFTg7Rea5KJUiGZX/TFvzQghYdq6UjF7dokmZb8ZI81WTN6f3fsNKkKBxA==" 213 | "resolved" "https://registry.npmjs.org/jaguarjs-jsdoc/-/jaguarjs-jsdoc-1.0.2.tgz" 214 | "version" "1.0.2" 215 | 216 | "js2xmlparser@^4.0.2": 217 | "integrity" "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==" 218 | "resolved" "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz" 219 | "version" "4.0.2" 220 | dependencies: 221 | "xmlcreate" "^2.0.4" 222 | 223 | "jsdoc@^4.0.2": 224 | "integrity" "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==" 225 | "resolved" "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz" 226 | "version" "4.0.2" 227 | dependencies: 228 | "@babel/parser" "^7.20.15" 229 | "@jsdoc/salty" "^0.2.1" 230 | "@types/markdown-it" "^12.2.3" 231 | "bluebird" "^3.7.2" 232 | "catharsis" "^0.9.0" 233 | "escape-string-regexp" "^2.0.0" 234 | "js2xmlparser" "^4.0.2" 235 | "klaw" "^3.0.0" 236 | "markdown-it" "^12.3.2" 237 | "markdown-it-anchor" "^8.4.1" 238 | "marked" "^4.0.10" 239 | "mkdirp" "^1.0.4" 240 | "requizzle" "^0.2.3" 241 | "strip-json-comments" "^3.1.0" 242 | "underscore" "~1.13.2" 243 | 244 | "klaw@^3.0.0": 245 | "integrity" "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==" 246 | "resolved" "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz" 247 | "version" "3.0.0" 248 | dependencies: 249 | "graceful-fs" "^4.1.9" 250 | 251 | "linkify-it@^3.0.1": 252 | "integrity" "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==" 253 | "resolved" "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz" 254 | "version" "3.0.3" 255 | dependencies: 256 | "uc.micro" "^1.0.1" 257 | 258 | "lodash@^4.17.14", "lodash@^4.17.15", "lodash@^4.17.21": 259 | "integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 260 | "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" 261 | "version" "4.17.21" 262 | 263 | "markdown-it-anchor@^8.4.1": 264 | "integrity" "sha512-sLODeRetZ/61KkKLJElaU3NuU2z7MhXf12Ml1WJMSdwpngeofneCRF+JBbat8HiSqhniOMuTemXMrsI7hA6XyA==" 265 | "resolved" "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.4.1.tgz" 266 | "version" "8.4.1" 267 | 268 | "markdown-it@*", "markdown-it@^12.3.2": 269 | "integrity" "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==" 270 | "resolved" "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz" 271 | "version" "12.3.2" 272 | dependencies: 273 | "argparse" "^2.0.1" 274 | "entities" "~2.1.0" 275 | "linkify-it" "^3.0.1" 276 | "mdurl" "^1.0.1" 277 | "uc.micro" "^1.0.5" 278 | 279 | "marked@^4.0.10": 280 | "integrity" "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==" 281 | "resolved" "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz" 282 | "version" "4.0.12" 283 | 284 | "math-intrinsics@^1.1.0": 285 | "integrity" "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" 286 | "resolved" "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz" 287 | "version" "1.1.0" 288 | 289 | "mdurl@^1.0.1": 290 | "integrity" "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" 291 | "resolved" "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz" 292 | "version" "1.0.1" 293 | 294 | "mime-db@1.44.0": 295 | "integrity" "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" 296 | "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz" 297 | "version" "1.44.0" 298 | 299 | "mime-types@^2.1.12": 300 | "integrity" "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==" 301 | "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz" 302 | "version" "2.1.27" 303 | dependencies: 304 | "mime-db" "1.44.0" 305 | 306 | "mkdirp@^1.0.4": 307 | "integrity" "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" 308 | "resolved" "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" 309 | "version" "1.0.4" 310 | 311 | "node-fetch@^2.7.0": 312 | "integrity" "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==" 313 | "resolved" "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" 314 | "version" "2.7.0" 315 | dependencies: 316 | "whatwg-url" "^5.0.0" 317 | 318 | "requizzle@^0.2.3": 319 | "integrity" "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==" 320 | "resolved" "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz" 321 | "version" "0.2.3" 322 | dependencies: 323 | "lodash" "^4.17.14" 324 | 325 | "strip-json-comments@^3.1.0": 326 | "integrity" "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" 327 | "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" 328 | "version" "3.1.1" 329 | 330 | "tr46@~0.0.3": 331 | "integrity" "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 332 | "resolved" "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" 333 | "version" "0.0.3" 334 | 335 | "typescript@^4.9.4": 336 | "integrity" "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" 337 | "resolved" "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz" 338 | "version" "4.9.4" 339 | 340 | "uc.micro@^1.0.1", "uc.micro@^1.0.5": 341 | "integrity" "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" 342 | "resolved" "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz" 343 | "version" "1.0.6" 344 | 345 | "underscore@~1.13.2": 346 | "integrity" "sha512-ekY1NhRzq0B08g4bGuX4wd2jZx5GnKz6mKSqFL4nqBlfyMGiG10gDFhDTMEfYmDL6Jy0FUIZp7wiRB+0BP7J2g==" 347 | "resolved" "https://registry.npmjs.org/underscore/-/underscore-1.13.2.tgz" 348 | "version" "1.13.2" 349 | 350 | "undici-types@~5.25.1": 351 | "integrity" "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" 352 | "resolved" "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz" 353 | "version" "5.25.3" 354 | 355 | "undici@^6.0.0": 356 | "integrity" "sha512-uROZWze0R0itiAKVPsYhFov9LxrPMHLMEQFszeI2gCN6bnIIZ8twzBCJcN2LJrBBLfrP0t1FW0g+JmKVl8Vk1g==" 357 | "resolved" "https://registry.npmjs.org/undici/-/undici-6.21.2.tgz" 358 | "version" "6.21.2" 359 | 360 | "webidl-conversions@^3.0.0": 361 | "integrity" "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 362 | "resolved" "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" 363 | "version" "3.0.1" 364 | 365 | "whatwg-url@^5.0.0": 366 | "integrity" "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==" 367 | "resolved" "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" 368 | "version" "5.0.0" 369 | dependencies: 370 | "tr46" "~0.0.3" 371 | "webidl-conversions" "^3.0.0" 372 | 373 | "xmlcreate@^2.0.4": 374 | "integrity" "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==" 375 | "resolved" "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz" 376 | "version" "2.0.4" 377 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![solvecaptcha-javascript](https://github.com/user-attachments/assets/60b0a294-4e51-4ff5-a101-82a1aebe33ab) 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | # JavaScript captcha solver (Node.js): Bypass reCAPTCHA, Cloudflare, GeeTest and more 11 | 12 | Use the [JavaScript captcha solver](https://solvecaptcha.com/captcha-solver/javascript-captcha-solver-bypass) to automatically bypass any captcha - including reCAPTCHA v2, Invisible, v3, Enterprise, Cloudflare Turnstile, GeeTest sliders, Amazon WAF, FunCaptcha, and both image and text-based challenges. 13 | 14 | ## ✅ Supported captcha solvers 15 | To get started quickly, check out the [Captcha Solver API](https://solvecaptcha.com/captcha-solver-api) documentation. 16 | 17 | ### Helpful links: 18 | - [reCAPTCHA v2 solver (Node.js + Puppeteer)](https://solvecaptcha.com/captcha-solver/recaptcha-v2-solver-bypass) 19 | - [reCAPTCHA v3 solver](https://solvecaptcha.com/captcha-solver/recaptcha-v3-solver-bypass) 20 | - [Text & Image captcha solver (Base64 / file input)]() 21 | - [Cloudflare captcha / Turnstile solver](https://solvecaptcha.com/captcha-solver/cloudflare-captcha-solver-bypass) 22 | - [Amazon captcha (WAF & login forms)](https://solvecaptcha.com/captcha-solver/amazon-captcha-solver-bypass) 23 | - [GeeTest slider solver](https://solvecaptcha.com/captcha-solver/slider-captcha-solver-bypass) 24 | - [FunCaptcha (Arkose Labs)](https://solvecaptcha.com/captcha-solver/funcaptcha-solver-bypass) 25 | - [Other custom captcha types](https://solvecaptcha.com/) 26 | 27 | ## 🛠️ Features 28 | - Fast and fully automated bypass 29 | - Works in **JavaScript** and **Node.js** environments 30 | - Compatible with **Puppeteer**, **Playwright**, and **Selenium** 31 | - Lightweight npm module with modern **async/await** support 32 | - Pay only for successful solves 33 | - 99.9% uptime 34 | - 24/7 support for developers and integration teams 35 | 36 | ## 📦 Use cases 37 | 38 | - Web scraping behind reCAPTCHA or Cloudflare walls 39 | - Automated form submission and login flows 40 | - QA pipelines and headless browser testing 41 | - Bypassing captchas in research or bot-detection evaluation 42 | - Custom browser automations using JavaScript or Node.js 43 | 44 | Need help integrating with your Node.js app or JS automation tools? [Open an issue](https://github.com/solvercaptcha/solvecaptcha-javascript/issues) or fork this repo to contribute. 45 | 46 | - [JavaScript captcha solver (Node.js): Bypass reCAPTCHA, Cloudflare, GeeTest and more](#javascript-captcha-solver-nodejs-bypass-recaptcha-cloudflare-geetest-and-more) 47 | - [Installation](#installation) 48 | - [Configuration](#configuration) 49 | - [SolveCaptcha instance options](#solvecaptcha-instance-options) 50 | - [Solve captcha](#solve-captcha) 51 | - [Image Captcha](#image-captcha) 52 | - [reCAPTCHA v2](#recaptcha-v2) 53 | - [reCAPTCHA v3](#recaptcha-v3) 54 | - [FunCaptcha](#funcaptcha) 55 | - [GeeTest](#geetest-captcha) 56 | - [GeeTest V4](#geetest-v4-captcha) 57 | - [Yandex Smart Captcha](#yandex-smart-captcha) 58 | - [Lemin Cropped Captcha](#lemin-cropped-captcha) 59 | - [Cloudflare Turnstile](#cloudflare-turnstile) 60 | - [Amazon WAF](#amazon-waf) 61 | - [Capy](#capy) 62 | - [ClickCaptcha](#clickcaptcha) 63 | - [DataDome CAPTCHA](#datadome-captcha) 64 | - [CyberSiARA](#cybersiara) 65 | - [MTCaptcha](#mtcaptcha) 66 | - [Friendly Captcha](#friendly-captcha) 67 | - [Bounding Box Method](#bounding-box-method) 68 | - [Grid](#grid) 69 | - [Text Captcha](#text-captcha) 70 | - [Canvas](#canvas) 71 | - [Rotate](#rotate) 72 | - [KeyCaptcha](#keycaptcha) 73 | - [Cutcaptcha](#cutcaptcha) 74 | - [Tencent](#tencent) 75 | - [atbCAPTCHA](#atbcaptcha) 76 | - [Audio Captcha](#audio-captcha) 77 | - [Other methods](#other-methods) 78 | - [goodReport](#goodreport) 79 | - [badReport](#badreport) 80 | - [balance](#balance) 81 | - [Proxies](#proxies) 82 | - [Examples](#examples) 83 | - [Examples using Puppeteer](#examples-using-puppeteer) 84 | - [Useful articles](#useful-articles) 85 | - [Get in touch](#get-in-touch) 86 | - [Join the team 👪](#join-the-team-) 87 | - [License](#license) 88 | - [Graphics and Trademarks](#graphics-and-trademarks) 89 | 90 | 91 | ## Installation 92 | You can install this package using NPM: 93 | 94 | ```sh 95 | npm install solvecaptcha-javascript 96 | ``` 97 | or Yarn: 98 | ```sh 99 | yarn add solvecaptcha-javascript 100 | ``` 101 | 102 | To install directly from GitHub: 103 | ```sh 104 | npm install github:solvercaptcha/solvecaptcha-javascript 105 | ``` 106 | 107 | ## Configuration 108 | 109 | You can create a SolveCaptcha instance as follows: 110 | 111 | ```js 112 | const SolveCaptcha = require("solvecaptcha-javascript") 113 | const solver = new SolveCaptcha.Solver("") 114 | ``` 115 | 116 | Additionally, several configuration options are available: 117 | 118 | ```javascript 119 | const apiKey = 'YOUR_API_KEY' 120 | const pollingInterval = 10 121 | 122 | const solver = new SolveCaptcha.Solver(apiKey, pollingInterval) 123 | ``` 124 | ### SolveCaptcha instance options 125 | 126 | | Option | Default value | Description | 127 | | ---------------- | -------------- | -------------------------------------------------------------------------------------------- | 128 | | apiKey | - | Your personal API key | 129 | | pollingInterval | 5000 | The delay in milliseconds between each request to the res.php API endpoint. It's not recommended to set this value below `5000` milliseconds (5 seconds). | 130 | 131 | ## Solve captcha 132 | 133 | When submitting an image-based captcha, you can include extra parameters to assist Solvecaptcha workers in solving it accurately. 134 | 135 | ### Captcha options 136 | 137 | | Option | Default Value | Description | 138 | | --------------- | ------------- | ----------------------------------------------------------------------------------------------------- | 139 | | numeric | 0 | Indicates whether the captcha includes only numbers, letters, or a mix [see more info in the API docs][post options] | 140 | | min_len | 0 | Minimum number of characters expected in the answer | 141 | | max_len | 0 | Maximum number of characters allowed in the answer | 142 | | phrase | 0 | Specifies whether the answer should consist of multiple words | 143 | | regsense | 0 | Indicates if case sensitivity should be considered in the answer | 144 | | calc | 0 | Specifies whether the captcha involves a mathematical expression to solve | 145 | | lang | - | Sets the language of the captcha; refer to the [list of supported languages] | 146 | | textinstructions| - | A hint or instruction shown to the workers along with the captcha image | 147 | 148 | Below are simple examples for each captcha type — take a look at the code samples provided. 149 | 150 | ### Image captcha 151 | 152 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#solving_normal_captcha) 153 | 154 | To solve a standard captcha (distorted text within an image), use the method below. It can also be applied for general text recognition in images. 155 | 156 | ```js 157 | const imageBase64 = fs.readFileSync("./examples/media/imageCaptcha_6e584.png", "base64") 158 | 159 | solver.imageCaptcha({ 160 | body: imageBase64, 161 | numeric: 4, 162 | min_len: 5, 163 | max_len: 5 164 | }) 165 | .then((res) => { 166 | console.log(res); 167 | }) 168 | .catch((err) => { 169 | console.log(err); 170 | }) 171 | ``` 172 | 173 | ### reCAPTCHA V2 174 | 175 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#solving_recaptchav2_new) 176 | 177 | Use this method to solve reCAPTCHA V2 and retrieve a token that allows you to bypass the verification. 178 | 179 | ```js 180 | solver.recaptcha({ 181 | pageurl: 'https://solvecaptcha.com/demo/recaptcha-v2', 182 | googlekey: '6LfD3PIbAAAAAJs_eEHvoOl75_83eXSqpPSRFJ_u' 183 | }) 184 | .then((res) => { 185 | console.log(res); 186 | }) 187 | .catch((err) => { 188 | console.log(err); 189 | }) 190 | ``` 191 | 192 | ### reCAPTCHA V3 193 | 194 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#solving_recaptchav3) 195 | 196 | This method is used to solve reCAPTCHA V3 and returns a token for verification. 197 | 198 | ```js 199 | solver.recaptcha({ 200 | pageurl: 'https://solvecaptcha.com/demo/recaptcha-v3', 201 | googlekey: '6Lcyqq8oAAAAAJE7eVJ3aZp_hnJcI6LgGdYD8lge', 202 | version: "v3", 203 | min_score: "0.4", 204 | action: 'demo_action' 205 | }) 206 | .then((res) => { 207 | console.log(res); 208 | }) 209 | .catch((err) => { 210 | console.log(err); 211 | }) 212 | ``` 213 | 214 | ### FunCaptcha 215 | 216 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#solving_funcaptcha_new) 217 | 218 | Method for solving FunCaptcha (Arkoselabs). Returns a verification token. 219 | 220 | ```js 221 | solver.funCaptcha({ 222 | pageurl: "https://funcaptcha.com/tile-game-lite-mode/fc/api/nojs/?pkey=804380F4-6844-FFA1-ED4E-5877CA1F1EA4&lang=en", 223 | publickey: "804380F4-6844-FFA1-ED4E-5877CA1F1EA4" 224 | }) 225 | .then((res) => { 226 | console.log(res); 227 | }) 228 | .catch((err) => { 229 | console.log(err); 230 | }) 231 | ``` 232 | 233 | ### GeeTest Captcha 234 | 235 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#solving_geetest) 236 | 237 | Method for solving GeeTest puzzle captcha. Returns a JSON object containing the required tokens. 238 | 239 | ```js 240 | // Read more about `challenge` on the page https://solvecaptcha.com/p/geetest 241 | solver.geetest({ 242 | pageurl: 'https://solvecaptcha.com/demo/geetest', 243 | gt: '81388ea1fc187e0c335c0a8907ff2625', 244 | challenge: '' 245 | }) 246 | .then((res) => { 247 | console.log(res); 248 | }) 249 | .catch((err) => { 250 | console.log(err); 251 | }) 252 | ``` 253 | 254 | ### GeeTest V4 Captcha 255 | 256 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#geetest-v4) 257 | 258 | Use this method to solve GeeTest v4 captcha. The response is returned in JSON format. 259 | 260 | ```js 261 | solver.geetestV4({ 262 | pageurl: 'https://solvecaptcha.com/demo/geetest-v4', 263 | captcha_id: 'e392e1d7fd421dc63325744d5a2b9c73' 264 | }) 265 | .then((res) => { 266 | console.log(res); 267 | }) 268 | .catch((err) => { 269 | console.log(err); 270 | }) 271 | ``` 272 | 273 | ### Yandex Smart Captcha 274 | 275 | Use this method to solve Yandex Smart Captcha and receive a token that allows you to bypass the verification. 276 | 277 | ```js 278 | solver.yandexSmart({ 279 | pageurl: "https://captcha-api.yandex.ru/demo", 280 | sitekey: "FEXfAbHQsToo97VidNVk3j4dC74nGW1DgdxjtNB9" 281 | }) 282 | .then((res) => { 283 | console.log(res); 284 | }) 285 | .catch((err) => { 286 | console.log(err); 287 | }) 288 | ``` 289 | 290 | ### Lemin Cropped Captcha 291 | 292 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#lemin) 293 | 294 | Use this method to solve Lemin captcha and obtain a token to bypass the verification process.. 295 | 296 | ```js 297 | solver.lemin({ 298 | pageurl:'https://solvecaptcha.com/demo/lemin', 299 | captcha_id: 'CROPPED_3dfdd5c_d1872b526b794d83ba3b365eb15a200b', 300 | div_id: 'lemin-cropped-captcha', 301 | api_server: 'api.leminnow.com' 302 | }) 303 | .then((res) => { 304 | console.log(res); 305 | }) 306 | .catch((err) => { 307 | console.log(err); 308 | }) 309 | ``` 310 | 311 | ### Cloudflare Turnstile 312 | 313 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#turnstile) 314 | 315 | Use this method to solve Cloudflare Turnstile captcha. Returns a JSON response containing the token. 316 | 317 | Turnstile captcha comes in two variants, one of which is the Cloudflare Turnstile Challenge page. For handling this type, we offer a [demo](https://github.com/solvercaptcha/cloudflare-demo). Check out this [demo](https://github.com/solvercaptcha/cloudflare-demo) if you need to solve captchas on the Cloudflare Turnstile Challenge page. 318 | 319 | ```js 320 | solver.cloudflareTurnstile({ 321 | pageurl: "https://app.nodecraft.com/login", 322 | sitekey: "0x4AAAAAAAAkg0s3VIOD10y4" 323 | }) 324 | .then((res) => { 325 | console.log(res); 326 | }) 327 | .catch((err) => { 328 | console.log(err); 329 | }) 330 | ``` 331 | 332 | ### Amazon WAF 333 | 334 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#amazon-waf) 335 | 336 | Use this method to solve Amazon WAF Captcha, also known as AWS WAF Captcha, which is part of Amazon AWS's intelligent threat mitigation system. Returns a JSON response containing the token. 337 | 338 | ```js 339 | //INFO: The `context` parameter is dynamic and must be retrieved from the page in real time for each request. 340 | solver.amazonWaf({ 341 | pageurl: "https://non-existent-example.execute-api.us-east-1.amazonaws.com/latest", 342 | sitekey: "AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AHMDLodoefdvyOnsHMRt...", 343 | context: "9BUgmlm48F92WUoqv97a49ZuEJJ50TCk9MVr3C7WMtQ0X6flVbufM4n8mjFLmbLVAPgaQ...", 344 | iv: "CgAHbCe2GgAAAAAj", 345 | }) 346 | .then((res) => { 347 | console.log(res); 348 | }) 349 | .catch((err) => { 350 | console.log(err); 351 | }) 352 | ``` 353 | 354 | ### Capy 355 | 356 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#solving_capy) 357 | 358 | Token-based method for bypassing Capy puzzle captcha verification. 359 | 360 | ```js 361 | solver.capyPuzzle({ 362 | pageurl: "https://www.capy.me/account/register/", 363 | captchakey: "PUZZLE_Cme4hZLjuZRMYC3uh14C52D3uNms5w" 364 | }) 365 | .then((res) => { 366 | console.log(res); 367 | }) 368 | .catch((err) => { 369 | console.log(err); 370 | }) 371 | ``` 372 | 373 | ### DataDome CAPTCHA 374 | 375 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#datadome) 376 | 377 | Use this method to solve DataDome captcha and get a token to bypass the protection. 378 | 379 | > [!IMPORTANT] 380 | > A proxy is required to solve the DataDome captcha. It is recommended to use residential proxies. 381 | 382 | ```js 383 | solver.dataDome({ 384 | pageurl: "https://rendezvousparis.hermes.com/client/register", 385 | captcha_url: "https://geo.captcha-delivery.com/captcha/?initialCid=AHrlqAAAAAMAEuQtkf4k1c0ABZhYZA%3D%3D&hash=789361B674144528D0B7EE76B35826&cid=mY4z7GNmh7Nt1lAFwpbNHAOcWPhyPgjHD2K1Pm~Od1iEKYLUnK3t7N2ZGUj8OqDK65cnwJHtHwd~t902vlwpSBA5l4ZHbS1Qszv~jEuEUJNQ_jMAjar2Kj3kq20MRJYh&t=fe&referer=https%3A%2F%2Frendezvousparis.hermes.com%2Fclient%2Fregister&s=40119&e=67fef144ac1a54dbd7507776367d2f9d5e36ec3add17fa22f3cb881db8385838", 386 | userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", 387 | proxy: "login:password@1.2.3.4:8888", // The (Username : Password @ Address : Port) of our chosen proxy 388 | proxytype: "http" // The 'Type' of proxy, http, https, socks, ect. 389 | }) 390 | .then((res) => { 391 | console.log(res); 392 | }) 393 | .catch((err) => { 394 | console.log(err); 395 | }) 396 | ``` 397 | 398 | ### CyberSiARA 399 | 400 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#cybersiara) 401 | 402 | Use this method to solve CyberSiARA captcha and receive a token to bypass the verification. 403 | 404 | ```js 405 | solver.cyberSiARA({ 406 | pageurl: "https://www.cybersiara.com/book-a-demo", 407 | master_url_id: "OXR2LVNvCuXykkZbB8KZIfh162sNT8S2", 408 | userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" 409 | }) 410 | .then((res) => { 411 | console.log(res); 412 | }) 413 | .catch((err) => { 414 | console.log(err); 415 | }) 416 | ``` 417 | 418 | ### MTCaptcha 419 | 420 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#mtcaptcha) 421 | 422 | Use this method to solve MTCaptcha and get a token that allows you to bypass the verification. 423 | 424 | ```js 425 | solver.mtCaptcha({ 426 | pageurl: "https://service.mtcaptcha.com/mtcv1/demo/index.html", 427 | sitekey: "MTPublic-DemoKey9M" 428 | }) 429 | .then((res) => { 430 | console.log(res); 431 | }) 432 | .catch((err) => { 433 | console.log(err); 434 | }) 435 | ``` 436 | 437 | ### Friendly Captcha 438 | 439 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#friendly-captcha) 440 | 441 | Use this method to solve Friendly Captcha and retrieve a token to bypass the verification process. 442 | 443 | > [!IMPORTANT] 444 | > For the token to work correctly, the captcha widget must not be loaded on the page. You need to block the request to `/friendlycaptcha/...module.min.js`. If the widget has already been loaded, there is a high chance the obtained token will be invalid. 445 | 446 | ```js 447 | solver.friendlyCaptcha({ 448 | pageurl: "https://geizhals.de/?liftban=1&from=/455973138?fsean=5901747021356", 449 | sitekey: "FCMST5VUMCBOCGQ9" 450 | }) 451 | .then((res) => { 452 | console.log(res); 453 | }) 454 | .catch((err) => { 455 | console.log(err); 456 | }) 457 | ``` 458 | 459 | ### ClickCaptcha 460 | 461 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#coordinates) 462 | 463 | The ClickCaptcha method returns coordinates of specific points on the captcha image. It's useful when the task requires clicking on certain areas within the image. 464 | 465 | ```js 466 | const imageBase64 = fs.readFileSync("./tests/media/coordinates.jpg", "base64") 467 | 468 | solver.coordinates({ 469 | body: imageBase64, 470 | textinstructions: 'Select all photos containing the boat' 471 | }) 472 | .then((res) => { 473 | console.log(res); 474 | }) 475 | .catch((err) => { 476 | console.log(err); 477 | }) 478 | ``` 479 | 480 | ### Bounding Box Method 481 | 482 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#bounding_box) 483 | 484 | Use the Bounding Box Method when you need to highlight specific objects in an image. To do this, provide both the image and the corresponding instructions for markup. Instructions can be submitted either as plain text or as a `base64`-encoded image. 485 | 486 | > [!IMPORTANT] 487 | > You must include either the `imginstructions` or `textinstructions` parameter. 488 | 489 | ```js 490 | solver.boundingBox({ 491 | image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAR4AAACwCAIAAAB...", 492 | textinstructions: "Circle all the cars in the image.", 493 | }) 494 | .then((res) => { 495 | console.log(res); 496 | }) 497 | .catch((err) => { 498 | console.log(err); 499 | }) 500 | ``` 501 | 502 | ### Grid 503 | 504 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#grid) 505 | 506 | This method is suitable for solving captchas where the image can be split into equal-sized segments, such as reCAPTCHA V2. A grid is overlaid on the image, and the response contains the numbers of the selected boxes. 507 | 508 | > [!IMPORTANT] 509 | > You must include either the `imginstructions` or `textinstructions` parameter. 510 | 511 | ```js 512 | solver.grid({ 513 | body: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAR4AAACwCAIAAAB...", 514 | textinstructions: "Select cars in the image" 515 | }) 516 | .then((res) => { 517 | console.log(res); 518 | }) 519 | .catch((err) => { 520 | console.log(err); 521 | }) 522 | ``` 523 | 524 | ### Text Captcha 525 | 526 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#solving_text_captcha) 527 | 528 | This method is used to bypass captchas that present a question in plain text and require a text-based answer. 529 | 530 | ```js 531 | solver.textCaptcha({ 532 | textcaptcha: "If tomorrow is Saturday, what day is today?", 533 | lang: 'en' 534 | }) 535 | .then((res) => { 536 | console.log(res); 537 | }) 538 | .catch((err) => { 539 | console.log(err); 540 | }) 541 | ``` 542 | 543 | ### Canvas 544 | 545 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#canvas) 546 | 547 | The canvas method is used when you need to outline an object on an image by drawing a line around it. It returns a set of coordinates for points that form a polygon. 548 | 549 | ```js 550 | solver.canvas({ 551 | body: 'iVBORw0KGgoAAAANSgAAAcIA...', 552 | imginstructions: '/9j/4AAQSkZJRgABAQEA...', 553 | textinstructions: 'Highlight the red CIRCLE' 554 | }) 555 | .then((res) => { 556 | console.log(res); 557 | }) 558 | .catch((err) => { 559 | console.log(err); 560 | }) 561 | ``` 562 | 563 | ### Rotate 564 | 565 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#solving_rotatecaptcha) 566 | 567 | This method is intended for solving captchas that require rotating an object, commonly used in FunCaptcha. It returns the angle of rotation needed. 568 | 569 | ```js 570 | solver.rotate({ 571 | body: imageBase64, 572 | textinstructions: "Rotate the object to the correct position" 573 | }) 574 | .then((res) => { 575 | console.log(res); 576 | }) 577 | .catch((err) => { 578 | console.log(err); 579 | }) 580 | ``` 581 | 582 | ### KeyCaptcha 583 | 584 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#solving_keycaptcha) 585 | 586 | Token-based method for solving KeyCaptcha challenges. 587 | 588 | ```js 589 | solver.keyCaptcha({ 590 | pageurl: "https://solvecaptcha.com/demo/keycaptcha", 591 | userId: '184015', 592 | sessionId: '0917788cad24ad3a69813c4fcd556061', 593 | webServerSign: '02f7f9669f1269595c4c69bcd4a3c52e', 594 | webServerSign2: 'd888700f6f324ec0f32b44c32c50bde1' 595 | }) 596 | .then((res) => { 597 | console.log(res); 598 | }) 599 | .catch((err) => { 600 | console.log(err); 601 | }) 602 | ``` 603 | 604 | ### Cutcaptcha 605 | 606 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#cutcaptcha) 607 | 608 | Use this method to solve Cutcaptcha. The response is returned in JSON format. 609 | 610 | ```js 611 | solver.cutCaptcha({ 612 | pageurl: "https://mysite.com/page/with/cutcaptcha", 613 | misery_key: "098e6a849af406142e3150dbf4e6d0538db2b51f", 614 | api_key: "SAs61IAI", 615 | }) 616 | .then((res) => { 617 | console.log(res); 618 | }) 619 | .catch((err) => { 620 | console.log(err); 621 | }) 622 | ``` 623 | 624 | ### Tencent 625 | 626 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#tencent) 627 | 628 | Use this method to solve Tencent captcha. The response is provided in JSON format. 629 | 630 | ```js 631 | solver.tencent({ 632 | pageurl: "https://mysite.com/page/with/tencent", 633 | appId: "189956587" 634 | }) 635 | .then((res) => { 636 | console.log(res); 637 | }) 638 | .catch((err) => { 639 | console.log(err); 640 | }) 641 | ``` 642 | 643 | ### atbCAPTCHA 644 | 645 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#atb-captcha) 646 | 647 | Use this method to solve the atbCAPTCHA challenge. It returns a token that allows you to bypass the captcha verification. 648 | 649 | ```js 650 | solver.atbCaptcha({ 651 | pageurl: "https://mysite.com/page/with/atbCAPTCHA", 652 | appId: "af25e409b33d722a95e56a230ff8771c", 653 | apiServer: "https://cap.aisecurius.com" 654 | }) 655 | .then((res) => { 656 | console.log(res); 657 | }) 658 | .catch((err) => { 659 | console.log(err); 660 | }) 661 | ``` 662 | 663 | ### Audio Captcha 664 | 665 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#audio-recognition) 666 | 667 | Use the method below to bypass an audio captcha (only `mp3` format is supported). You must specify the language using `lang = 'en'`. Supported languages include: "en", "ru", "de", "el", "pt", and "fr". 668 | 669 | ```js 670 | solver.audio({ 671 | body: "SUQzBAAAAAAAHFRTU0UAAAA...", 672 | lang: "en" 673 | }) 674 | .then((res) => { 675 | console.log(res); 676 | }) 677 | .catch((err) => { 678 | console.log(err); 679 | }) 680 | ``` 681 | 682 | ## Other methods 683 | 684 | ### goodReport 685 | 686 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#reporting-answers) 687 | 688 | Use this method to report a correct captcha solution. 689 | 690 | ```js 691 | solver.goodReport('7031846604') 692 | ``` 693 | 694 | ### badReport 695 | 696 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#reporting-answers) 697 | 698 | Use this method to report an incorrect captcha solution. 699 | 700 | ```js 701 | solver.badReport('7031854546') 702 | ``` 703 | 704 | ### balance 705 | 706 | [Description of the API method.](https://solvecaptcha.com/solvecaptcha-api#additional-methods) 707 | 708 | Use this method to check the balance of your account. 709 | 710 | ```js 711 | solver.balance() 712 | .then((res) => { 713 | console.log(res) 714 | }) 715 | ``` 716 | 717 | ## Proxies 718 | 719 | You can include your proxy as an additional parameter when using methods like: recaptcha, funcaptcha, geetest, geetest v4, keycaptcha, capy puzzle, lemin, turnstile, amazon waf, DataDome, CyberSiARA, MTCaptcha, Friendly Captcha, and others. The proxy will be passed to the API to assist in solving the captcha. 720 | 721 | Example: Solving reCAPTCHA V2 with a proxy: 722 | ```js 723 | solver.recaptcha({ 724 | pageurl: 'https://solvecaptcha.com/demo/recaptcha-v2', 725 | googlekey: '6LfD3PIbAAAAAJs_eEHvoOl75_83eXSqpPSRFJ_u', 726 | proxy: 'HTTPS', 727 | proxytype: 'login:password@123.123.123.123:3128' 728 | }) 729 | ``` 730 | ## Examples 731 | 732 | Examples for solving all supported captcha types can be found in the [examples] directory. 733 | 734 | ## Useful articles 735 | 736 | - [Solve and bypass Google reCAPTCHA, Image CAPTCHA, Cloudflare Challenge and any captcha in Selenium with captcha solver.](https://solvecaptcha.com/captcha-solver/selenium-captcha-solver-bypass) 737 | - [Solve and bypass Google reCAPTCHA, Arkose FunCaptcha, Cloudflare Turnstile, and any captcha in Puppeteer with captcha solver.](https://solvecaptcha.com/captcha-solver/puppeteer-captcha-solver-bypass) 738 | 739 | ## Get in touch 740 | 741 | 742 | 743 | 744 | ## Become part of the team 👪 745 | 746 | There are plenty of ways to get involved — development is just one of them! Discover your next opportunity. We're hiring AI specialists, scrapers, developers, tech support, and more! 😍 747 | 748 | 749 | 750 | ## License 751 | 752 | This repository’s code is distributed under the MIT License. For more information, see the [LICENSE](./LICENSE) file. 753 | 754 | ### Graphics and Trademarks 755 | 756 | Graphics and trademarks included in this repository are not licensed under the MIT License. For permission to use these assets, please contact our support team. 757 | 758 | 759 | [Solvecaptcha]: https://solvecaptcha.com/ 760 | [JavaScript captcha solver]: https://solvecaptcha.com/captcha-solver/javascript-captcha-solver-bypass 761 | [post options]: https://solvecaptcha.com/solvecaptcha-api#normal_post 762 | [list of supported languages]: https://solvecaptcha.com/solvecaptcha-api#language 763 | [examples]: ./examples 764 | -------------------------------------------------------------------------------- /src/structs/solvecaptcha.ts: -------------------------------------------------------------------------------- 1 | import fetch from "node-fetch"; 2 | import FormData from "form-data"; 3 | import { APIError } from "./solvecaptchaError"; 4 | import * as utils from "../utils/generic"; 5 | import getProviderData from "./providers/providers"; 6 | import { softId } from "./constants/constants"; 7 | import checkCaptchaParams from "../utils/checkCaptchaParams"; 8 | import renameParams from "../utils/renameParams"; 9 | 10 | const provider = getProviderData(); 11 | 12 | export interface paramsRecaptcha { 13 | pageurl: string; 14 | googlekey: string; 15 | invisible?: 0 | 1; 16 | datas?: string; 17 | domain?: string; 18 | cookies?: string; 19 | userAgent?: string; 20 | header_acao?: boolean; 21 | pingback?: string; 22 | soft_id?: number; 23 | proxy?: string; 24 | proxytype?: string; 25 | action?: string; 26 | enterprise?: 0 | 1; 27 | min_score?: number; 28 | version?: string; 29 | } 30 | 31 | export interface paramsFunCaptcha { 32 | publickey: string; 33 | pageurl: string; 34 | surl?: string; 35 | header_acao?: boolean; 36 | pingback?: string; 37 | proxy?: string; 38 | proxytype?: string; 39 | userAgent?: string; 40 | data?: string; 41 | } 42 | 43 | export interface paramsImageCaptcha { 44 | body: string; 45 | phrase?: 0 | 1; 46 | regsense?: 0 | 1; 47 | numeric?: 0 | 1 | 2 | 3 | 4; 48 | calc?: 0 | 1; 49 | min_len?: 0 | string | number; // 1..20 50 | max_len?: 0 | string | number; // 1..20 51 | language?: 0 | 1 | 2; 52 | lang?: string; 53 | pingback?: string; 54 | textinstructions?: string; 55 | } 56 | 57 | export interface paramsGeetest { 58 | gt: string; 59 | challenge: string; 60 | pageurl: string; 61 | api_server?: string; 62 | offline?: number | boolean; 63 | new_captcha?: number | boolean; 64 | pingback?: string; 65 | soft_id?: number; 66 | proxy?: string; 67 | proxytype?: string; 68 | userAgent?: string; 69 | } 70 | 71 | export interface yandexSmart { 72 | pageurl: string; 73 | sitekey: string; 74 | pingback?: string; 75 | proxy?: string; 76 | proxytype?: string; 77 | userAgent?: string; 78 | } 79 | 80 | export interface paramsGeeTestV4 { 81 | pageurl: string; 82 | captcha_id: string; 83 | pingback?: string; 84 | proxy?: string; 85 | proxytype?: string; 86 | userAgent?: string; 87 | } 88 | 89 | export interface paramsLemin { 90 | pageurl: string; 91 | captcha_id: string; 92 | div_id: string; 93 | api_server?: string; 94 | pingback?: string; 95 | proxy?: string; 96 | proxytype?: string; 97 | } 98 | 99 | export interface paramsAmazonWAF { 100 | pageurl: string; 101 | sitekey: string; 102 | iv: string; 103 | context: string; 104 | challenge_script?: string; 105 | captcha_script?: string; 106 | header_acao?: boolean; 107 | pingback?: string; 108 | soft_id?: number; 109 | proxy?: string; 110 | proxytype?: string; 111 | } 112 | 113 | export interface paramsTurnstile { 114 | pageurl: string; 115 | sitekey: string; 116 | action?: string; 117 | data?: string; 118 | header_acao?: boolean; 119 | pingback?: string; 120 | soft_id?: number; 121 | proxy?: string; 122 | proxytype?: string; 123 | } 124 | 125 | export interface paramsCapyPuzzle { 126 | pageurl: string; 127 | captchakey: string; 128 | api_server?: string; 129 | version?: string; 130 | pingback?: string; 131 | proxy?: string; 132 | proxytype?: string; 133 | } 134 | 135 | export interface paramsCoordinates { 136 | body: string; 137 | language?: 0 | 1 | 2; 138 | lang?: string; 139 | pingback?: string; 140 | textinstructions?: string; 141 | imginstructions?: string; 142 | } 143 | 144 | export interface paramsDataDome { 145 | pageurl: string; 146 | captcha_url: string; 147 | userAgent: string; 148 | pingback?: string; 149 | proxy: string; 150 | proxytype: string; 151 | } 152 | 153 | export interface paramsCyberSiARA { 154 | pageurl: string; 155 | master_url_id: string; 156 | userAgent: string; 157 | pingback?: string; 158 | proxy?: string; 159 | proxytype?: string; 160 | } 161 | 162 | export interface paramsMTCaptcha { 163 | pageurl: string; 164 | sitekey: string; 165 | userAgent?: string; 166 | pingback?: string; 167 | proxy?: string; 168 | proxytype?: string; 169 | } 170 | 171 | export interface paramsCutcaptcha { 172 | pageurl: string; 173 | miseryKey: string; 174 | apiKey: string; 175 | pingback?: string; 176 | proxy?: string; 177 | proxytype?: string; 178 | } 179 | 180 | export interface friendlyCaptcha { 181 | pageurl: string; 182 | sitekey: string; 183 | pingback?: string; 184 | proxy?: string; 185 | proxytype?: string; 186 | } 187 | 188 | export interface paramsBoundingBox { 189 | image: string; 190 | textinstructions?: string; 191 | imginstructions?: string; 192 | } 193 | 194 | export interface paramsGrid { 195 | body: string; 196 | recaptcha: number; 197 | canvas?: number; 198 | rows?: number; 199 | cols?: number; 200 | minClicks?: number; 201 | maxClicks?: number; 202 | previousId?: string; 203 | imgType?: string; 204 | textinstructions?: string; 205 | imginstructions?: string; 206 | canSkip?: number; 207 | lang?: string; 208 | pingback?: string; 209 | } 210 | 211 | export interface paramsTextcaptcha { 212 | textcaptcha: string; 213 | lang?: string; 214 | pingback?: string; 215 | } 216 | 217 | export interface paramsRotateCaptcha { 218 | body: string; 219 | angle?: number; 220 | pingback?: string; 221 | lang?: string; 222 | textinstructions?: string; 223 | imginstructions?: string; 224 | } 225 | 226 | export interface paramsKeyCaptcha { 227 | pageurl: string; 228 | userId: string; 229 | sessionId: string; 230 | webServerSign: string; 231 | webServerSign2: string; 232 | pingback?: string; 233 | proxy?: string; 234 | proxytype?: string; 235 | } 236 | 237 | export interface paramsTencent { 238 | pageurl: string; 239 | appId: string; 240 | pingback?: string; 241 | proxy?: string; 242 | proxytype?: string; 243 | } 244 | 245 | export interface paramsAtbCaptcha { 246 | pageurl: string; 247 | appId: string; 248 | apiServer: string; 249 | pingback?: string; 250 | proxy?: string; 251 | proxytype?: string; 252 | } 253 | 254 | export interface paramsAudioCaptcha { 255 | body: string; 256 | lang: string; 257 | pingback?: string; 258 | } 259 | 260 | /** 261 | * An object containing properties of the captcha solution. 262 | * @typedef {Object} CaptchaAnswer 263 | * @param {string} data The solution to the captcha 264 | * @param {string} id The captcha ID 265 | */ 266 | interface CaptchaAnswer { 267 | /** The solution to the captcha */ 268 | data: string; 269 | /** The ID of the captcha solve */ 270 | id: string; 271 | } 272 | 273 | /** 274 | * The main solvecaptcha class, housing all API calls and api interactions. 275 | * 276 | */ 277 | export class Solver { 278 | public _apikey: string; 279 | public _pollingFrequency: number; 280 | public _headerACAO: number; 281 | 282 | /** 283 | * The constructor for the solvecaptcha Solver class. 284 | * 285 | * @param {string} apikey The API key to use 286 | * @param {number} pollingFrequency The frequency to poll for requests 287 | * 288 | */ 289 | constructor( 290 | apikey: string, 291 | pollingFrequency: number = 5000, 292 | enableACAO: boolean = true 293 | ) { 294 | this._apikey = apikey; 295 | this._pollingFrequency = pollingFrequency; 296 | this._headerACAO = enableACAO ? 1 : 0; 297 | } 298 | 299 | /** The API key this instance is using */ 300 | public get apikey() { 301 | return this._apikey; 302 | } 303 | /** Frequency the instance polls for updates */ 304 | public get pollingFrequency() { 305 | return this._pollingFrequency; 306 | } 307 | /** Set the API key for this instance */ 308 | public set apikey(update: string) { 309 | this._apikey = update; 310 | } 311 | 312 | private get in() { 313 | return provider.in; 314 | } 315 | private get res() { 316 | return provider.res; 317 | } 318 | private get defaultPayload() { 319 | return { 320 | key: this.apikey, 321 | json: 1, 322 | header_acao: this._headerACAO, 323 | soft_id: softId, 324 | }; 325 | } 326 | 327 | /** 328 | * Returns the remaining account balance. 329 | * 330 | * @return {Promise} Remaining balance 331 | * @throws APIError 332 | * @example 333 | * solver.balance() 334 | * .then((res) => { 335 | * console.log(res) 336 | * }) 337 | */ 338 | public async balance(): Promise { 339 | const res = await fetch( 340 | this.res + 341 | utils.objectToURI({ 342 | ...this.defaultPayload, 343 | action: "getbalance", 344 | }) 345 | ); 346 | const result = await res.text(); 347 | 348 | try { 349 | const data = JSON.parse(result); 350 | if (data.status == 1) { 351 | return parseFloat(data.request); 352 | } 353 | throw new APIError(data.request); 354 | } catch { 355 | throw new APIError(result); 356 | } 357 | } 358 | 359 | /** 360 | * @private 361 | * 362 | * Polls for a captcha, finding out if it's been completed 363 | * @param {string} id Captcha ID 364 | * 365 | * @returns {Promise} 366 | * @throws APIError 367 | */ 368 | private async pollResponse(id: string): Promise { 369 | const payload = { 370 | ...this.defaultPayload, 371 | action: "get", 372 | id: id, 373 | }; 374 | 375 | await utils.sleep(this.pollingFrequency); 376 | 377 | const res = await fetch(this.res + utils.objectToURI(payload)); 378 | const result = await res.text(); 379 | 380 | let data; 381 | try { 382 | data = JSON.parse(result); 383 | if (data.status == 1) { 384 | let dataJSON = { ...data, data: data.request, id: id }; 385 | delete dataJSON.request; 386 | return dataJSON; 387 | } 388 | } catch { 389 | throw new APIError(result); 390 | } 391 | switch (data.request) { 392 | case "CAPCHA_NOT_READY": 393 | return this.pollResponse(id); 394 | default: { 395 | throw new APIError(data.request); 396 | } 397 | } 398 | } 399 | 400 | /** 401 | * ### Solves a google reCAPTCHA V2 | V3. 402 | * 403 | * [Read more about other reCAPTCHA parameters](https://solvecaptcha.com/solvecaptcha-api#solving_recaptchav2_new). 404 | * 405 | * @param {{pageurl, googlekey, cookies, proxy, proxytype, userAgent, invisible, datas, pingback, action, enterprise, min_score, version, domain}} params Object 406 | * @param {string} params.pageurl The URL the captcha appears on. 407 | * @param {string} params.googlekey Value of `k` or `data-sitekey` parameter you found on page. 408 | * @param {string} params.cookies Your cookies that will be passed to our worker who solve the captha. 409 | * @param {string} params.proxy Format: `login:password@123.123.123.123:3128`. You can find more info about proxies [here](https://solvecaptcha.com/solvecaptcha-api#proxies). 410 | * @param {string} params.proxytype Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 411 | * @param {string} params.userAgent Your `userAgent` that will be passed to our worker and used to solve the captcha. 412 | * @param {number} params.invisible `1` - means that reCAPTCHA is invisible. `0` - normal reCAPTCHA. 413 | * @param {string} params.datas Value of `data-s` parameter you found on page. Curenttly applicable for Google Search and other Google services. 414 | * @param {string} params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 415 | * @param {string} params.action Value of `action` parameter you found on page. 416 | * @param {number} params.enterprise `1` - defines that you're sending reCAPTCHA Enterpise. 417 | * @param {number} params.min_score The score needed for resolution reCAPTCHA V3. Currently it's almost impossible to get token with score higher than `0.3` 418 | * @param {string} params.version `v2` — defines that you're sending a reCAPTCHA V2. `v3` — defines that you're sending a reCAPTCHA V3. 419 | * @param {string} params.domain Domain used to load the captcha: `google.com` or `recaptcha.net` 420 | * 421 | * @returns {Promise} The result from the solve. 422 | * @throws APIError 423 | * @example 424 | * solver.recaptcha({ 425 | * pageurl: 'https://solvecaptcha.com/demo/recaptcha-v2', 426 | * googlekey: '6LfD3PIbAAAAAJs_eEHvoOl75_83eXSqpPSRFJ_u' 427 | * }) 428 | * .then((res) => { 429 | * console.log(res); 430 | * }) 431 | * .catch((err) => { 432 | * console.log(err); 433 | * }) 434 | */ 435 | public async recaptcha(params: paramsRecaptcha): Promise { 436 | checkCaptchaParams(params, "userrecaptcha"); 437 | const payload = { 438 | ...params, 439 | method: "userrecaptcha", 440 | ...this.defaultPayload, 441 | }; 442 | 443 | const response = await fetch(this.in + utils.objectToURI(payload)); 444 | const result = await response.text(); 445 | 446 | let data; 447 | try { 448 | data = JSON.parse(result); 449 | } catch { 450 | throw new APIError(result); 451 | } 452 | 453 | if (data.status == 1) { 454 | return this.pollResponse(data.request); 455 | } else { 456 | throw new APIError(data.request); 457 | } 458 | } 459 | 460 | 461 | /** 462 | * ### Solves a GeeTest Captcha. 463 | * 464 | * [Read more about parameters and solving for Geetest captcha](https://solvecaptcha.com/solvecaptcha-api#solving_geetest). 465 | * 466 | * @param {{ gt, challenge, api_server, offline, new_captcha, 467 | * pageurl, pingback, proxy, proxytype, userAgent }} params 468 | * @param {string} params.gt Value of gt parameter found on site 469 | * @param {string} params.challenge Value of challenge parameter found on site 470 | * @param {string} params.pageurl The URL the captcha appears on 471 | * @param {string} params.api_server The URL of the api_server (recommended) 472 | * @param {number} params.offline In rare cases `initGeetest` can be called with `offline` parameter on the target page. If the call uses offline: true, set the value to `1`. 473 | * @param {number} params.new_captcha In rare cases `initGeetest` can be called with `new_captcha` parameter. If the call uses `new_captcha: true`, set the value to `1`. Mostly used with offline parameter. 474 | * @param {string} params.pingback URL for `pingback` (callback) response that will be sent when captcha is solved. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 475 | * @param {string} params.proxy Format: `login:password@123.123.123.123:3128`. You can find more info about proxies [here](https://solvecaptcha.com/solvecaptcha-api#proxies). 476 | * @param {string} params.proxytype Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 477 | * @param {string} params.userAgent Your `userAgent` that will be passed to our worker and used to solve the captcha. 478 | * 479 | * @returns {Promise} The result from the solve. 480 | * @throws APIError 481 | * @example 482 | * ;(async () => { 483 | * 484 | * // Warning: Attention, the `challenge` value is not static but dynamic. 485 | * // You need to find the queries that makes the captcha on the page to API. 486 | * // Then you need to make request to this API and get new `challenge`. 487 | * 488 | * // For page https://solvecaptcha.com/demo/geetest, api address is https://solvecaptcha.com/api/v1/captcha-demo/gee-test/init-params?t=${t} 489 | * // Also note that when make request to API, the request uses the dynamic parameter `t` 490 | * 491 | * // You can read more about sending GeeTest here https://solvecaptcha.com/solvecaptcha-api#solving_geetest, or here https://solvecaptcha.com/p/geetest 492 | * // In this example I solve GeeTest from page https://solvecaptcha.com/demo/geetest 493 | * 494 | * const t = new Date().getTime() 495 | * // below i make a request to get a new `challenge`. 496 | * const response = await fetch(`https://solvecaptcha.com/api/v1/captcha-demo/gee-test/init-params?t=${t}`) 497 | * const data = await response.json() 498 | * 499 | * const params = { 500 | * pageurl: 'https://solvecaptcha.com/demo/geetest', 501 | * gt: data.gt, 502 | * challenge: data.challenge 503 | * } 504 | * 505 | * const res = await solver.geetest(params) 506 | * try { 507 | * console.log(res) 508 | * } catch (error) { 509 | * console.error(error); 510 | * } 511 | * })() 512 | */ 513 | public async geetest(params: paramsGeetest): Promise { 514 | checkCaptchaParams(params, "geetest"); 515 | const payload = { 516 | ...params, 517 | method: "geetest", 518 | ...this.defaultPayload, 519 | }; 520 | 521 | const response = await fetch(this.in + utils.objectToURI(payload)); 522 | const result = await response.text(); 523 | 524 | let data; 525 | try { 526 | data = JSON.parse(result); 527 | } catch { 528 | throw new APIError(result); 529 | } 530 | 531 | if (data.status == 1) { 532 | return this.pollResponse(data.request); 533 | } else { 534 | throw new APIError(data.request); 535 | } 536 | } 537 | 538 | /** 539 | * ### Solves a GeeTest V4 Captcha. 540 | * 541 | * This method accepts an object with the following fields: `pageurl`, `captcha_id`, `pingback`, `proxy`, `proxytype`, `userAgent`. 542 | * The `pageurl` and `captcha_id` fields are required. 543 | * 544 | * @param {{pageurl, captcha_id, pingback, proxy, proxytype, userAgent}} params The method geetestV4 takes arguments as an object. 545 | * @param {string} params.pageurl Full URL of the page where you see Geetest V4 captcha. 546 | * @param {string} params.captcha_id Required parameter. Value of `captcha_id` parameter you found on target website. 547 | * @param {string} params.pingback An optional param. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 548 | * @param {string} params.proxy An optional param. Format: `login:password@123.123.123.123:3128`. You can find more info about proxies [here](https://solvecaptcha.com/solvecaptcha-api#proxies). 549 | * @param {string} params.proxytype An optional param. Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 550 | * @param {string} params.userAgent An optional param. Your `userAgent` that will be passed to our worker and used to solve the captcha. 551 | * 552 | * @returns {Promise} The result from the solve. 553 | * @throws APIError 554 | * @example 555 | * solver.geetestV4({ 556 | * pageurl: 'https://solvecaptcha.com/demo/geetest-v4', 557 | * captcha_id: 'e392e1d7fd421dc63325744d5a2b9c73' 558 | * }) 559 | * .then((res) => { 560 | * console.log(res) 561 | * }) 562 | * .catch((err) => { 563 | * console.log(err); 564 | * }) 565 | */ 566 | public async geetestV4(params: paramsGeeTestV4): Promise { 567 | checkCaptchaParams(params, "geetest_v4"); 568 | const payload = { 569 | ...params, 570 | method: "geetest_v4", 571 | ...this.defaultPayload, 572 | }; 573 | 574 | const response = await fetch(this.in + utils.objectToURI(payload)); 575 | const result = await response.text(); 576 | 577 | let data; 578 | try { 579 | data = JSON.parse(result); 580 | } catch { 581 | throw new APIError(result); 582 | } 583 | 584 | if (data.status == 1) { 585 | return this.pollResponse(data.request); 586 | } else { 587 | throw new APIError(data.request); 588 | } 589 | } 590 | 591 | /** 592 | * ### Method for sending Yandex Smart Captcha. 593 | * 594 | * This method accepts an object with the following fields: `pageurl`, `sitekey`, `pingback`, `proxy`, `proxytype`. 595 | * The `pageurl` and `sitekey` fields are required. 596 | * 597 | * @param {{pageurl, sitekey, pingback, proxy, proxytype, userAgent}} params The method takes arguments as an object. 598 | * @param {string} params.pageurl Required parameter. URL of the page where the captcha is located. 599 | * @param {string} params.sitekey Required parameter. The `sitekey` value you found on the captcha page. 600 | * @param {string} params.pingback An optional param. 601 | * @param {string} params.proxy An optional param. Format: `login:password@123.123.123.123:3128`. 602 | * @param {string} params.proxytype An optional param. Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 603 | * @param {string} params.userAgent An optional param. Your `userAgent` that will be passed to our worker and used to solve the captcha. 604 | * 605 | * @returns {Promise} The result from the solve. 606 | * @throws APIError 607 | * @example 608 | * solver.yandexSmart({ 609 | * pageurl: "https://captcha-api.yandex.ru/demo", 610 | * sitekey: "FEXfAbHQsToo97VidNVk3j4dC74nGW1DgdxjtNB9" 611 | * }) 612 | * .then((res) => { 613 | * console.log(res) 614 | * }) 615 | * .catch((err) => { 616 | * console.log(err); 617 | * }) 618 | */ 619 | public async yandexSmart(params: yandexSmart): Promise { 620 | checkCaptchaParams(params, "yandex"); 621 | const payload = { 622 | ...params, 623 | method: "yandex", 624 | ...this.defaultPayload, 625 | }; 626 | 627 | const response = await fetch(this.in + utils.objectToURI(payload)); 628 | const result = await response.text(); 629 | 630 | let data; 631 | try { 632 | data = JSON.parse(result); 633 | } catch { 634 | throw new APIError(result); 635 | } 636 | 637 | if (data.status == 1) { 638 | return this.pollResponse(data.request); 639 | } else { 640 | throw new APIError(data.request); 641 | } 642 | } 643 | 644 | /** 645 | * ### Solves a image-based captcha. 646 | * 647 | * [Read more about parameters for image captcha](https://solvecaptcha.com/solvecaptcha-api#solving_normal_captcha). 648 | * 649 | * @param {{ body, 650 | * phrase, 651 | * regsense, 652 | * numeric, 653 | * calc, 654 | * min_len, 655 | * max_len, 656 | * language, 657 | * lang, 658 | * textinstructions, 659 | * pingback }} params Extra properties to pass to solvecaptcha. 660 | * @param {string} params.body Base64 image data for the captcha. 661 | * @param {number} params.phrase Captcha contains two or more words? `1` - Yes. `0` - No. 662 | * @param {number} params.regsense Captcha is case sensitive? `1` - Yes. `0` - No. 663 | * @param {number} params.numeric `0` - not specified. `1` - captcha contains only numbers. `2` - captcha contains only letters. `3` - captcha contains only numbers OR only letters. `4` - captcha MUST contain both numbers AND letters. 664 | * @param {number} params.calc Does captcha require calculations? (e.g. type the result 4 + 8 = ) `1` - Yes. `0` - No. 665 | * @param {number} params.min_len `1..20` - minimal number of symbols in captcha. `0` - not specified. 666 | * @param {number} params.max_len `1..20` - maximal number of symbols in captcha. `0` - not specified. 667 | * @param {number} params.language `0` - not specified. `1` - Cyrillic captcha. `2` - Latin captcha 668 | * @param {string} params.lang Language code. [See the list of supported languages](https://solvecaptcha.com/solvecaptcha-api#language). 669 | * @param {string} params.textinstructions Text will be shown to worker to help him to solve the captcha correctly. For example: type red symbols only. 670 | * @param {string} params.pingback URL for `pingback` (callback) response that will be sent when captcha is solved. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 671 | * 672 | * @returns {Promise} The result from the solve 673 | * @throws APIError 674 | * @example 675 | * const imageBase64 = fs.readFileSync("./tests/media/imageCaptcha_6e584.png", "base64") 676 | * 677 | * solver.imageCaptcha({ 678 | * body: imageBase64, 679 | * numeric: 4, 680 | * min_len: 5, 681 | * max_len: 5 682 | * }) 683 | * .then((res) => { 684 | * console.log(res); 685 | * }) 686 | * .catch((err) => { 687 | * console.log(err); 688 | * }) 689 | */ 690 | public async imageCaptcha( 691 | params: paramsImageCaptcha 692 | ): Promise { 693 | checkCaptchaParams(params, "base64"); 694 | 695 | const payload = { 696 | ...params, 697 | ...this.defaultPayload, 698 | method: "base64", 699 | }; 700 | const URL = this.in; 701 | const response = await fetch(URL, { 702 | body: utils.toFormData(payload), 703 | method: "post", 704 | }); 705 | const result = await response.text(); 706 | 707 | let data; 708 | try { 709 | data = JSON.parse(result); 710 | } catch { 711 | throw new APIError(result); 712 | } 713 | 714 | if (data.status == 1) { 715 | return this.pollResponse(data.request); 716 | } else { 717 | throw new APIError(data.request); 718 | } 719 | } 720 | 721 | /** 722 | * ### Solves Arkose Labs FunCaptcha. 723 | * 724 | * [Read more](https://solvecaptcha.com/solvecaptcha-api#solving_funcaptcha_new) about other solving and other parameters for Arkose Labs FunCaptcha. 725 | * 726 | * @param {{pageurl, publicKey, surl, data, pingback, proxy, proxytype, userAgent}} params Object 727 | * @param {string} params.publicKey The FunCaptcha Public Key 728 | * @param {string} params.pageurl The URL to the website the captcha is seen on 729 | * @param {string} params.surl The FunCaptcha Service URL (recommended) 730 | * @param {string} params.data Custom data to pass to FunCaptcha. For example: `'data': '{"blob": "foo"}'`. 731 | * @param {string} params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 732 | * @param {string} params.proxy Format: `login:password@123.123.123.123:3128` You can find more info about proxies [here](https://solvecaptcha.com/solvecaptcha-api#proxies). 733 | * @param {string} params.proxytype Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 734 | * @param {string} params.userAgent Your `userAgent` that will be passed to our worker and used to solve the captcha. 735 | * 736 | * @returns {Promise} The result from the solve 737 | * @throws APIError 738 | * 739 | * @example 740 | * solver.funCaptcha({ 741 | * pageurl: "https://funcaptcha.com/tile-game-lite-mode/fc/api/nojs/?pkey=804380F4-6844-FFA1-ED4E-5877CA1F1EA4&lang=en", 742 | * publickey: "804380F4-6844-FFA1-ED4E-5877CA1F1EA4" 743 | * }) 744 | * .then((res) => { 745 | * console.log(res); 746 | * }) 747 | * .catch((err) => { 748 | * console.log(err); 749 | * }) 750 | */ 751 | public async funCaptcha(params: paramsFunCaptcha): Promise { 752 | checkCaptchaParams(params, "funcaptcha"); 753 | const payload = { 754 | ...params, 755 | method: "funcaptcha", 756 | ...this.defaultPayload, 757 | }; 758 | 759 | const response = await fetch(this.in + utils.objectToURI(payload)); 760 | const result = await response.text(); 761 | 762 | let data; 763 | try { 764 | data = JSON.parse(result); 765 | } catch { 766 | throw new APIError(result); 767 | } 768 | 769 | if (data.status == 1) { 770 | return this.pollResponse(data.request); 771 | } else { 772 | throw new APIError(data.request); 773 | } 774 | } 775 | 776 | /** 777 | * 778 | * ### Solves a Lemin captcha 779 | * 780 | * [Read more about other Lemin captcha parameters](https://solvecaptcha.com/solvecaptcha-api#lemin). 781 | * 782 | * @param {{ pageurl, captcha_id, div_id, api_server, pingback, proxy, proxytype}} params Object 783 | * @param {string} params.pageurl The URL the captcha appears on. 784 | * @param {string} params.captcha_id Value of `captcha_id` parameter you found on page. 785 | * @param {string} params.div_id Value `id` of captcha pareent `
` element. 786 | * @param {string} params.api_server The domain part of script URL you found on page. Default value: `https://api.leminnow.com/` 787 | * @param {string} params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 788 | * @param {string} params.proxy Format: `login:password@123.123.123.123:3128` You can find more info about proxies [here](https://solvecaptcha.com/solvecaptcha-api#proxies). 789 | * @param {string} params.proxytype Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 790 | * 791 | * @example 792 | * solver.lemin({ 793 | * pageurl:'https://solvecaptcha.com/demo/lemin', 794 | * captcha_id: 'CROPPED_3dfdd5c_d1872b526b794d83ba3b365eb15a200b', 795 | * div_id: 'lemin-cropped-captcha', 796 | * api_server: 'api.leminnow.com' 797 | * }) 798 | * .then((res) => { 799 | * console.log(res); 800 | * }) 801 | * .catch((err) => { 802 | * console.log(err); 803 | * }) 804 | */ 805 | public async lemin(params: paramsLemin): Promise { 806 | checkCaptchaParams(params, "lemin"); 807 | const payload = { 808 | ...params, 809 | method: "lemin", 810 | ...this.defaultPayload, 811 | }; 812 | 813 | const response = await fetch(this.in + utils.objectToURI(payload)); 814 | const result = await response.text(); 815 | 816 | let data; 817 | try { 818 | data = JSON.parse(result); 819 | } catch { 820 | throw new APIError(result); 821 | } 822 | 823 | if (data.status == 1) { 824 | return this.pollResponse(data.request); 825 | } else { 826 | throw new APIError(data.request); 827 | } 828 | } 829 | 830 | /** 831 | * 832 | * ### Solves Amazon WAF captcha 833 | * 834 | * [Read more about "Amazon WAF" captcha](https://solvecaptcha.com/solvecaptcha-api#amazon-waf). 835 | * 836 | * @param {{ pageurl, sitekey, iv, context, challenge_script, captcha_script, pingback, proxy, proxytype}} params The `amazonWaf` method takes arguments as an object. Thus, the `pageurl`, `sitekey`, `iv`, `context` fields in the passed object are mandatory. 837 | * @param {string} params.pageurl Is the full `URL` of page where you were challenged by the captcha. 838 | * @param {string} params.sitekey Is a value of `key` parameter in the page source. 839 | * @param {string} params.iv Is a value of `iv` parameter in the page source. 840 | * @param {string} params.context Is a value of `context` parameter in the page source. 841 | * @param {string} params.challenge_script The source URL of `challenge.js` script on the page. 842 | * @param {string} params.captcha_script The source URL of `captcha.js` script on the page. 843 | * @param {string} params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 844 | * @param {string} params.proxy Format: `login:password@123.123.123.123:3128` You can find more info about proxies [here](https://solvecaptcha.com/solvecaptcha-api#proxies). 845 | * @param {string} params.proxytype Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 846 | * 847 | * @example 848 | * solver.amazonWaf({ 849 | * pageurl: "https://non-existent-example.execute-api.us-east-1.amazonaws.com/latest", 850 | * sitekey: "AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AHMDLodoefdvyOnsHMRtEKQAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMUX+ZqwwuANRnZujSAgEQgDvHSxUQmVBuyUtumoW2n4ccTG7xQN1r3X/zz41qmQaYv9SSSvQrjIoDXKaUQ23tVb4ii8+uljuRdz/HPA==", 851 | * context: "9BUgmlm48F92WUoqv97a49ZuEJJ50TCk9MVr3C7WMtQ0X6flVbufM4n8mjFLmbLVAPgaQ1Jydeaja94iAS49ljb+sUNLoukWedAQZKrlY4RdbOOzvcFqmD/ZepQFS9N5w15Exr4VwnVq+HIxTsDJwRviElWCdzKDebN/mk8/eX2n7qJi5G3Riq0tdQw9+C4diFZU5E97RSeahejOAAJTDqduqW6uLw9NsjJBkDRBlRjxjn5CaMMo5pYOxYbGrM8Un1JH5DMOLeXbq1xWbC17YSEoM1cRFfTgOoc+VpCe36Ai9Kc=", 852 | * iv: "CgAHbCe2GgAAAAAj", 853 | * }) 854 | * .then((res) => { 855 | * console.log(res); 856 | * }) 857 | * .catch((err) => { 858 | * console.log(err); 859 | * }) 860 | */ 861 | public async amazonWaf(params: paramsAmazonWAF): Promise { 862 | checkCaptchaParams(params, "amazon_waf"); 863 | const payload = { 864 | ...params, 865 | method: "amazon_waf", 866 | ...this.defaultPayload, 867 | }; 868 | 869 | const response = await fetch(this.in + utils.objectToURI(payload)); 870 | const result = await response.text(); 871 | 872 | let data; 873 | try { 874 | data = JSON.parse(result); 875 | } catch { 876 | throw new APIError(result); 877 | } 878 | 879 | if (data.status == 1) { 880 | return this.pollResponse(data.request); 881 | } else { 882 | throw new APIError(data.request); 883 | } 884 | } 885 | 886 | /** 887 | * 888 | * ### Solves Cloudflare Turnstile captcha 889 | * 890 | * [Read more about Cloudflare Turnstile captcha](https://solvecaptcha.com/solvecaptcha-api#turnstile). 891 | * 892 | * @param {{ pageurl, sitekey, action, data, pingback, proxy, proxytype}} params The `cloudflareTurnstile` method takes arguments as an object. Thus, the `pageurl`, `sitekey` fields in the passed object are mandatory. 893 | * @param {string} params.pageurl Full `URL` of the page where you see the captcha. 894 | * @param {string} params.sitekey Is a value of `sitekey` parameter in the page source. 895 | * @param {string} params.action Value of optional `action` parameter you found on page. 896 | * @param {string} params.data Value of optional `data` parameter you found on page. 897 | * @param {string} params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 898 | * @param {string} params.proxy Format: `login:password@123.123.123.123:3128` You can find more info about proxies [here](https://solvecaptcha.com/solvecaptcha-api#proxies). 899 | * @param {string} params.proxytype Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 900 | * 901 | * @example 902 | * solver.cloudflareTurnstile({ 903 | * pageurl: "https://app.nodecraft.com/login", 904 | * sitekey: "0x4AAAAAAAAkg0s3VIOD10y4" 905 | * }) 906 | * .then((res) => { 907 | * console.log(res); 908 | * }) 909 | * .catch((err) => { 910 | * console.log(err); 911 | * }) 912 | */ 913 | public async cloudflareTurnstile( 914 | params: paramsTurnstile 915 | ): Promise { 916 | checkCaptchaParams(params, "turnstile"); 917 | const payload = { 918 | ...params, 919 | method: "turnstile", 920 | ...this.defaultPayload, 921 | }; 922 | 923 | const response = await fetch(this.in + utils.objectToURI(payload)); 924 | const result = await response.text(); 925 | 926 | let data; 927 | try { 928 | data = JSON.parse(result); 929 | } catch { 930 | throw new APIError(result); 931 | } 932 | 933 | if (data.status == 1) { 934 | return this.pollResponse(data.request); 935 | } else { 936 | throw new APIError(data.request); 937 | } 938 | } 939 | 940 | /** 941 | * ### Solves a Coordinates captcha. 942 | * 943 | * @param {{ body, imginstructions, textinstructions, language, lang, pingback }} params parameters Coordinates Captcha as an object. 944 | * @param {string} params.body Base64-encoded captcha image. 945 | * @param {string} params.imginstructions Base64-encoded image with instruction for solving captcha. 946 | * @param {string} params.textinstructions Text will be shown to worker to help him to solve the captcha correctly. For example: click on all objects in red color. 947 | * @param {number} params.language `0` - not specified. `1` - Cyrillic captcha. `2` - Latin captcha 948 | * @param {string} params.lang Language code. [See the list of supported languages](https://solvecaptcha.com/solvecaptcha-api#language). 949 | * @param {string} params.pingback URL for `pingback` (callback) response that will be sent when captcha is solved. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 950 | * 951 | * @returns {Promise} The result from the solve 952 | * 953 | * @example 954 | * const imageBase64 = fs.readFileSync("./tests/media/captchaImage.jpg", "base64") 955 | * 956 | * solver.coordinates({ 957 | * body: imageBase64, 958 | * textinstructions: 'Select all photos containing the boat' 959 | * }) 960 | * .then((res) => { 961 | * console.log(res); 962 | * }) 963 | * .catch((err) => { 964 | * console.log(err); 965 | * }) 966 | */ 967 | public async coordinates(params: paramsCoordinates): Promise { 968 | checkCaptchaParams(params, "base64"); 969 | 970 | const payload = { 971 | ...params, 972 | method: "base64", 973 | coordinatescaptcha: 1, 974 | ...this.defaultPayload, 975 | }; 976 | 977 | const URL = this.in; 978 | const response = await fetch(URL, { 979 | method: "post", 980 | body: utils.toFormData(payload), 981 | }); 982 | const result = await response.text(); 983 | 984 | let data; 985 | try { 986 | data = JSON.parse(result); 987 | } catch { 988 | throw new APIError(result); 989 | } 990 | 991 | if (data.status == 1) { 992 | return this.pollResponse(data.request); 993 | } else { 994 | throw new APIError(data.request); 995 | } 996 | } 997 | 998 | /** 999 | * ### Solves Capy Puzzle captcha 1000 | * 1001 | * @param {{ pageurl, captchakey, api_server, version, pingback, proxy, proxytype}} params Parameters Capy Puzzle Captcha as an object. 1002 | * @param {string} params.pageurl Full `URL`of the page where you see the captcha. 1003 | * @param {string} params.captchakey Value of `captchakey` parameter you found on page. 1004 | * @param {string} params.api_server The domain part of script URL you found on page. Default value: `https://jp.api.capy.me/`. 1005 | * @param {string} params.version The version of captcha task: `puzzle` (assemble a puzzle) or `avatar` (drag an object).. 1006 | * @param {string} params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 1007 | * @param {string} params.proxy Format: `login:password@123.123.123.123:3128` You can find more info about proxies [here](https://solvecaptcha.com/solvecaptcha-api#proxies). 1008 | * @param {string} params.proxytype Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 1009 | * 1010 | * @example 1011 | * solver.capyPuzzle({ 1012 | * pageurl: "https://www.capy.me/account/register/", 1013 | * captchakey: "PUZZLE_Cme4hZLjuZRMYC3uh14C52D3uNms5w" 1014 | * }) 1015 | * .then((res) => { 1016 | * console.log(res); 1017 | * }) 1018 | * .catch((err) => { 1019 | * console.log(err); 1020 | * }) 1021 | */ 1022 | public async capyPuzzle(params: paramsCapyPuzzle): Promise { 1023 | checkCaptchaParams(params, "capy"); 1024 | 1025 | const payload = { 1026 | ...params, 1027 | method: "capy", 1028 | ...this.defaultPayload, 1029 | }; 1030 | 1031 | const response = await fetch(this.in + utils.objectToURI(payload)); 1032 | const result = await response.text(); 1033 | 1034 | let data; 1035 | try { 1036 | data = JSON.parse(result); 1037 | } catch { 1038 | throw new APIError(result); 1039 | } 1040 | 1041 | if (data.status == 1) { 1042 | return this.pollResponse(data.request); 1043 | } else { 1044 | throw new APIError(data.request); 1045 | } 1046 | } 1047 | 1048 | /** 1049 | * ### Solves DataDome captcha 1050 | * 1051 | * @param {{ pageurl, captcha_url, userAgent, pingback, proxy, proxytype}} params Parameters DataDome Captcha as an object. 1052 | * @param {string} params.pageurl Full `URL` of the page where you see the captcha. 1053 | * @param {string} params.captcha_url The value of the `src` parameter for the `iframe` element containing the captcha on the page. 1054 | * @param {string} params.userAgent ser-Agent of your MODERN browser 1055 | * @param {string} params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 1056 | * @param {string} params.proxy Format: `login:password@123.123.123.123:3128` You can find more info about proxies [here](https://solvecaptcha.com/solvecaptcha-api#proxies). 1057 | * @param {string} params.proxytype Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 1058 | * 1059 | * @example 1060 | * solver.dataDome({ 1061 | * pageurl: "https://rendezvousparis.hermes.com/client/register", 1062 | * captcha_url: "https://geo.captcha-delivery.com/captcha/?initialCid=AHrlqAAAAAMAEuQtkf4k1c0ABZhYZA%3D%3D&hash=789361B674144528D0B7EE76B35826&cid=mY4z7GNmh7Nt1lAFwpbNHAOcWPhyPgjHD2K1Pm~Od1iEKYLUnK3t7N2ZGUj8OqDK65cnwJHtHwd~t902vlwpSBA5l4ZHbS1Qszv~jEuEUJNQ_jMAjar2Kj3kq20MRJYh&t=fe&referer=https%3A%2F%2Frendezvousparis.hermes.com%2Fclient%2Fregister&s=40119&e=67fef144ac1a54dbd7507776367d2f9d5e36ec3add17fa22f3cb881db8385838", 1063 | * userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", 1064 | * proxy: "1.2.3.4:8888:user:password", 1065 | * proxytype: "http" 1066 | * }) 1067 | * .then((res) => { 1068 | * console.log(res); 1069 | * }) 1070 | * .catch((err) => { 1071 | * console.log(err); 1072 | * }) 1073 | */ 1074 | public async dataDome(params: paramsDataDome): Promise { 1075 | checkCaptchaParams(params, "datadome"); 1076 | 1077 | const payload = { 1078 | ...params, 1079 | method: "datadome", 1080 | ...this.defaultPayload, 1081 | }; 1082 | 1083 | const response = await fetch(this.in + utils.objectToURI(payload)); 1084 | const result = await response.text(); 1085 | 1086 | let data; 1087 | try { 1088 | data = JSON.parse(result); 1089 | } catch { 1090 | throw new APIError(result); 1091 | } 1092 | 1093 | if (data.status == 1) { 1094 | return this.pollResponse(data.request); 1095 | } else { 1096 | throw new APIError(data.request); 1097 | } 1098 | } 1099 | 1100 | /** 1101 | * ### Solves CyberSiARA captcha 1102 | * 1103 | * @param {{ pageurl, master_url_id, userAgent, pingback, proxy, proxytype}} params Parameters CyberSiARA Captcha as an object. 1104 | * @param {string} params.pageurl Full `URL` of the page where you see the captcha. 1105 | * @param {string} params.master_url_id The value of `MasterUrlId` parameter obtained from the request to the endpoint `API/CyberSiara/GetCyberSiara`. 1106 | * @param {string} params.userAgent ser-Agent of your MODERN browser 1107 | * @param {string} params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 1108 | * @param {string} params.proxy Format: `login:password@123.123.123.123:3128` You can find more info about proxies [here](https://solvecaptcha.com/solvecaptcha-api#proxies). 1109 | * @param {string} params.proxytype Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 1110 | * 1111 | * @example 1112 | * solver.cyberSiARA({ 1113 | * pageurl: "https://www.cybersiara.com/book-a-demo", 1114 | * master_url_id: "OXR2LVNvCuXykkZbB8KZIfh162sNT8S2", 1115 | * userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" 1116 | * }) 1117 | * .then((res) => { 1118 | * console.log(res); 1119 | * }) 1120 | * .catch((err) => { 1121 | * console.log(err); 1122 | * }) 1123 | */ 1124 | public async cyberSiARA(params: paramsCyberSiARA): Promise { 1125 | checkCaptchaParams(params, "cybersiara"); 1126 | 1127 | const payload = { 1128 | ...params, 1129 | method: "cybersiara", 1130 | ...this.defaultPayload, 1131 | }; 1132 | 1133 | const response = await fetch(this.in + utils.objectToURI(payload)); 1134 | const result = await response.text(); 1135 | 1136 | let data; 1137 | try { 1138 | data = JSON.parse(result); 1139 | } catch { 1140 | throw new APIError(result); 1141 | } 1142 | 1143 | if (data.status == 1) { 1144 | return this.pollResponse(data.request); 1145 | } else { 1146 | throw new APIError(data.request); 1147 | } 1148 | } 1149 | 1150 | /** 1151 | * ### Solves MTCaptcha 1152 | * 1153 | * @param {{ pageurl, sitekey, userAgent, pingback, proxy, proxytype}} params Parameters MTCaptcha as an object. 1154 | * @param {string} params.pageurl Full `URL` of the page where you see the captcha. 1155 | * @param {string} params.sitekey TThe value of `sitekey` parameter found on the page. 1156 | * @param {string} params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 1157 | * @param {string} params.proxy Format: `login:password@123.123.123.123:3128` You can find more info about proxies [here](https://solvecaptcha.com/solvecaptcha-api#proxies). 1158 | * @param {string} params.proxytype Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 1159 | * 1160 | * @example 1161 | * solver.mtCaptcha({ 1162 | * pageurl: "https://service.mtcaptcha.com/mtcv1/demo/index.html", 1163 | * sitekey: "MTPublic-DemoKey9M" 1164 | * }) 1165 | * .then((res) => { 1166 | * console.log(res); 1167 | * }) 1168 | * .catch((err) => { 1169 | * console.log(err); 1170 | * }) 1171 | */ 1172 | public async mtCaptcha(params: paramsMTCaptcha): Promise { 1173 | checkCaptchaParams(params, "mt_captcha"); 1174 | 1175 | const payload = { 1176 | ...params, 1177 | method: "mt_captcha", 1178 | ...this.defaultPayload, 1179 | }; 1180 | 1181 | const response = await fetch(this.in + utils.objectToURI(payload)); 1182 | const result = await response.text(); 1183 | 1184 | let data; 1185 | try { 1186 | data = JSON.parse(result); 1187 | } catch { 1188 | throw new APIError(result); 1189 | } 1190 | 1191 | if (data.status == 1) { 1192 | return this.pollResponse(data.request); 1193 | } else { 1194 | throw new APIError(data.request); 1195 | } 1196 | } 1197 | 1198 | /** 1199 | * ### Solves a Cutcaptcha. 1200 | * 1201 | * Use this method to solve Cutcaptcha. Returns the response in JSON. 1202 | * [Read more about Cutcaptcha Method](https://solvecaptcha.com/solvecaptcha-api#cutcaptcha). 1203 | * 1204 | * @param {{ pageurl, miseryKey, apiKey, pingback, proxy, proxytype }} params Parameters for solving Cutcaptcha as an object. 1205 | * @param {string} params.pageurl The URL where the captcha is located. 1206 | * @param {string} params.miseryKey The value of `CUTCAPTCHA_MISERY_KEY` variable defined on page. 1207 | * @param {string} params.apiKey The value of `data-apikey` attribute of iframe's body. Also the name of javascript file included on the page 1208 | * @param {string} [params.pingback] Optional param. URL for pingback (callback) response when captcha is solved. 1209 | * @param {string} [params.proxy] Optional param. Proxy to use while solving the captcha. Format: `login:password@123.123.123.123:3128`. 1210 | * @param {string} [params.proxytype] Optional param. Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 1211 | * 1212 | * @returns {Promise} The result from the solve. 1213 | * @throws APIError 1214 | * 1215 | * @example 1216 | * solver.cutCaptcha({ 1217 | * pageurl: "https://mysite.com/page/with/cutcaptcha", 1218 | * miseryKey: "098e6a849af406142e3150dbf4e6d0538db2b51f", 1219 | * apiKey: "SAs61IAI", 1220 | * }) 1221 | * .then((res) => { 1222 | * console.log(res); 1223 | * }) 1224 | * .catch((err) => { 1225 | * console.log(err); 1226 | * }) 1227 | */ 1228 | public async cutCaptcha(params: paramsCutcaptcha): Promise { 1229 | params = renameParams(params); 1230 | checkCaptchaParams(params, "cutcaptcha"); 1231 | 1232 | const payload = { 1233 | ...params, 1234 | method: "cutcaptcha", 1235 | ...this.defaultPayload, 1236 | }; 1237 | 1238 | const URL = this.in; 1239 | const response = await fetch(URL, { 1240 | body: utils.toFormData(payload), 1241 | method: "post", 1242 | }); 1243 | const result = await response.text(); 1244 | 1245 | let data; 1246 | try { 1247 | data = JSON.parse(result); 1248 | } catch { 1249 | throw new APIError(result); 1250 | } 1251 | 1252 | if (data.status == 1) { 1253 | return this.pollResponse(data.request); 1254 | } else { 1255 | throw new APIError(data.request); 1256 | } 1257 | } 1258 | 1259 | /** 1260 | * ### Solves Friendly Captcha 1261 | * 1262 | * @param {{ pageurl, sitekey, pingback, proxy, proxytype}} params Parameters Friendly Captcha as an object. 1263 | * @param {string} params.pageurl Full `URL` of the page where you see the captcha. 1264 | * @param {string} params.sitekey The value of `data-apikey` or `data-sitekey` parameter found on the page. 1265 | * @param {string} params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 1266 | * @param {string} params.proxy Format: `login:password@123.123.123.123:3128` You can find more info about proxies [here](https://solvecaptcha.com/solvecaptcha-api#proxies). 1267 | * @param {string} params.proxytype Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 1268 | * 1269 | * @example 1270 | * solver.friendlyCaptcha({ 1271 | * pageurl: "https://geizhals.de/?liftban=1&from=/455973138?fsean=5901747021356", 1272 | * sitekey: "FCMST5VUMCBOCGQ9" 1273 | * }) 1274 | * .then((res) => { 1275 | * console.log(res); 1276 | * }) 1277 | * .catch((err) => { 1278 | * console.log(err); 1279 | * }) 1280 | */ 1281 | public async friendlyCaptcha( 1282 | params: friendlyCaptcha 1283 | ): Promise { 1284 | checkCaptchaParams(params, "friendly_captcha"); 1285 | 1286 | const payload = { 1287 | ...params, 1288 | method: "friendly_captcha", 1289 | ...this.defaultPayload, 1290 | }; 1291 | 1292 | const response = await fetch(this.in + utils.objectToURI(payload)); 1293 | const result = await response.text(); 1294 | 1295 | let data; 1296 | try { 1297 | data = JSON.parse(result); 1298 | } catch { 1299 | throw new APIError(result); 1300 | } 1301 | 1302 | if (data.status == 1) { 1303 | return this.pollResponse(data.request); 1304 | } else { 1305 | throw new APIError(data.request); 1306 | } 1307 | } 1308 | 1309 | /** 1310 | * ### Bounding Box Method 1311 | * 1312 | * @param {{ image, textinstructions, imginstructions }} params Parameters Bounding Box Method as an object. 1313 | * @param {string} params.image Image containing data for markup. The image must be encoded in `Base64` format. 1314 | * @param {string} params.textinstructions Text will be shown to worker to help him to select object on the image correctly. For example: "*Select cars in the image*". **Optional parameter**, if the instruction already exists in the form of the `imginstructions`. 1315 | * @param {string} params.imginstructions Image with instruction for worker to help him to select object on the image correctly. The image must be encoded in `Base64` format. **Optional parameter**, if the instruction already exists in the form of the `textinstructions`. 1316 | * 1317 | * @example 1318 | * solver.boundingBox({ 1319 | * image: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgG...", 1320 | * textinstructions: "Select cars in the image" 1321 | * }) 1322 | * .then((res) => { 1323 | * console.log(res); 1324 | * }) 1325 | * .catch((err) => { 1326 | * console.log(err); 1327 | * }) 1328 | */ 1329 | public async boundingBox(params: paramsBoundingBox): Promise { 1330 | checkCaptchaParams(params, "bounding_box"); 1331 | 1332 | const payload = { 1333 | ...params, 1334 | method: "bounding_box", 1335 | ...this.defaultPayload, 1336 | }; 1337 | 1338 | const URL = this.in; 1339 | const response = await fetch(URL, { 1340 | body: utils.toFormData(payload), 1341 | method: "post", 1342 | }); 1343 | const result = await response.text(); 1344 | 1345 | let data; 1346 | try { 1347 | data = JSON.parse(result); 1348 | } catch { 1349 | throw new APIError(result); 1350 | } 1351 | 1352 | if (data.status == 1) { 1353 | return this.pollResponse(data.request); 1354 | } else { 1355 | throw new APIError(data.request); 1356 | } 1357 | } 1358 | 1359 | /** 1360 | * ### Grid method 1361 | * 1362 | * The method can be used to bypass tasks where a grid is applied to an image and you need to click on grid tiles, like reCAPTCHA images. 1363 | * 1364 | * @param {{ body, textinstructions, imginstructions, rows, cols, minClicks, maxClicks, imgType, previousId, canSkip, lang, pingback}} params Parameters Grid Method as an object. 1365 | * @param {string} params.body `Base64`- encoded captcha image. 1366 | * @param {string} params.textinstructions Text will be shown to worker to help him to select object on the image correctly. For example: "*Select cars in the image*". **Optional parameter**, if the instruction already exists in the form of the `imginstructions`. 1367 | * @param {string} params.imginstructions Image with instruction for worker to help him to select object on the image correctly. The image must be encoded in `Base64` format. **Optional parameter**, if the instruction already exists in the form of the `textinstructions`. 1368 | * @param {number} params.rows Number of rows in grid captcha. 1369 | * @param {number} params.cols Number of columns in grid captcdha. 1370 | * @param {number} params.minClicks The minimum number of tiles that must be selected. Can't be more than `rows` * `cols`. 1371 | * @param {number} params.maxClicks The maximum number of tiles that can be selected on the image. 1372 | * @param {string} params.imgType The image will be recognized using Computer Vision. Supported value options: `recaptcha`, `funcaptcha`, `funcaptcha_compare`. [More info here](https://solvecaptcha.com/solvecaptcha-api#grid). 1373 | * @param {string} params.previousId Id of your previous request with the same captcha challenge. 1374 | * @param {number} params.canSkip Set the value to `1` only if it's possible that there's no images matching to the instruction. We'll provide a button "No matching images" to worker and you will receive `No_matching_images` as answer. 1375 | * @param {string} params.lang Language code. [See the list of supported languages](https://solvecaptcha.com/solvecaptcha-api#language). 1376 | * @param {string} params.pingback params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 1377 | * 1378 | * @example 1379 | * solver.grid({ 1380 | * body: 'iVBORw0KGgoAAAANSUhEUgAAAcIA...', 1381 | * textinstructions: "Select cars in the image", 1382 | * imginstructions: '/9j/4AAQSkZJRgABAQEA...' 1383 | * }) 1384 | * .then((res) => { 1385 | * console.log(res); 1386 | * }) 1387 | * .catch((err) => { 1388 | * console.log(err); 1389 | * }) 1390 | */ 1391 | public async grid(params: paramsGrid): Promise { 1392 | checkCaptchaParams(params, "grid"); 1393 | 1394 | params = await renameParams(params); 1395 | 1396 | const payload = { 1397 | ...params, 1398 | method: "base64", 1399 | recaptcha: 1, 1400 | ...this.defaultPayload, 1401 | }; 1402 | 1403 | const URL = this.in; 1404 | const response = await fetch(URL, { 1405 | body: utils.toFormData(payload), 1406 | method: "post", 1407 | }); 1408 | const result = await response.text(); 1409 | 1410 | let data; 1411 | try { 1412 | data = JSON.parse(result); 1413 | } catch { 1414 | throw new APIError(result); 1415 | } 1416 | 1417 | if (data.status == 1) { 1418 | return this.pollResponse(data.request); 1419 | } else { 1420 | throw new APIError(data.request); 1421 | } 1422 | } 1423 | 1424 | /** 1425 | * ### Text Captcha method 1426 | * 1427 | * Text Captcha is a type of captcha that is represented as text and doesn't contain images. Usually you have to answer a question to pass the verification. For example: "If tomorrow is Saturday, what day is today?". 1428 | * [Read more about Text Captcha Method](https://solvecaptcha.com/solvecaptcha-api#text-captcha). 1429 | * 1430 | * @param {{ textcaptcha, lang, pingback}} params Parameters Text Captcha Method as an object. 1431 | * @param {string} params.textcaptcha Text Captcha is a type of captcha that is represented as text and doesn't contain images. Usually you have to answer a question to pass the verification. 1432 | * @param {string} params.lang Language code. [See the list of supported languages](https://solvecaptcha.com/solvecaptcha-api#language). 1433 | * @param {string} params.pingback params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 1434 | * 1435 | * @example 1436 | * solver.text({ 1437 | * textcaptcha: "If tomorrow is Saturday, what day is today?", 1438 | * lang: 'en' 1439 | * }) 1440 | * .then((res) => { 1441 | * console.log(res); 1442 | * }) 1443 | * .catch((err) => { 1444 | * console.log(err); 1445 | * }) 1446 | */ 1447 | public async text(params: paramsTextcaptcha): Promise { 1448 | checkCaptchaParams(params, "textcaptcha"); 1449 | 1450 | params = await renameParams(params); 1451 | 1452 | const payload = { 1453 | ...params, 1454 | ...this.defaultPayload, 1455 | }; 1456 | 1457 | const URL = this.in; 1458 | const response = await fetch(URL, { 1459 | body: utils.toFormData(payload), 1460 | method: "post", 1461 | }); 1462 | const result = await response.text(); 1463 | 1464 | let data; 1465 | try { 1466 | data = JSON.parse(result); 1467 | } catch { 1468 | throw new APIError(result); 1469 | } 1470 | 1471 | if (data.status == 1) { 1472 | return this.pollResponse(data.request); 1473 | } else { 1474 | throw new APIError(data.request); 1475 | } 1476 | } 1477 | 1478 | /** 1479 | * ### Canvas method 1480 | * 1481 | * This method can be used to bypass tasks in which you need to circle an object or line in an image. 1482 | * [Read more about Canvas Method](https://solvecaptcha.com/solvecaptcha-api#canvas). 1483 | * 1484 | * @param {{ body, textinstructions, imginstructions, canSkip, lang, pingback}} params Parameters Canvas as an object. 1485 | * @param {string} params.body `Base64`- encoded captcha image. 1486 | * @param {string} params.textinstructions Text will be shown to worker to help him to select object on the image correctly. For example: "*Select cars in the image*". **Optional parameter**, if the instruction already exists in the form of the `imginstructions`. 1487 | * @param {string} params.imginstructions Image with instruction for worker to help him to select object on the image correctly. The image must be encoded in `Base64` format. **Optional parameter**, if the instruction already exists in the form of the `textinstructions`. 1488 | * @param {number} params.canSkip Set the value to `1` only if it's possible that there's no images matching to the instruction. We'll provide a button "No matching images" to worker and you will receive `No_matching_images` as answer. 1489 | * @param {string} params.lang Language code. [See the list of supported languages](https://solvecaptcha.com/solvecaptcha-api#language). 1490 | * @param {string} params.pingback params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://solvecaptcha.com/solvecaptcha-api#pingback). 1491 | * 1492 | * @example 1493 | * solver.canvas({ 1494 | * body: 'iVBORw0KGgoAAAANSgAAAcIA...', 1495 | * imginstructions: '/9j/4AAQSkZJRgABAQEA...', 1496 | * textinstructions: 'Highlight the red CIRCLE' 1497 | * }) 1498 | * .then((res) => { 1499 | * console.log(res); 1500 | * }) 1501 | * .catch((err) => { 1502 | * console.log(err); 1503 | * }) 1504 | */ 1505 | public async canvas(params: paramsGrid): Promise { 1506 | checkCaptchaParams(params, "canvas"); 1507 | 1508 | params = await renameParams(params); 1509 | 1510 | const payload = { 1511 | ...params, 1512 | recaptcha: 1, 1513 | canvas: 1, 1514 | method: "base64", 1515 | ...this.defaultPayload, 1516 | }; 1517 | 1518 | const URL = this.in; 1519 | const response = await fetch(URL, { 1520 | body: utils.toFormData(payload), 1521 | method: "post", 1522 | }); 1523 | const result = await response.text(); 1524 | 1525 | let data; 1526 | try { 1527 | data = JSON.parse(result); 1528 | } catch { 1529 | throw new APIError(result); 1530 | } 1531 | 1532 | if (data.status == 1) { 1533 | return this.pollResponse(data.request); 1534 | } else { 1535 | throw new APIError(data.request); 1536 | } 1537 | } 1538 | 1539 | /** 1540 | * ### Rotate method 1541 | * 1542 | * This method can be used to solve a captcha that asks to rotate an object. It is mostly used to bypass FunCaptcha. Returns the rotation angle. 1543 | * [Read more about Rotate Method](https://solvecaptcha.com/solvecaptcha-api#solving_rotatecaptcha). 1544 | * 1545 | * @param {{ body, angle, pingback, lang, textinstructions, imginstructions }} params Parameters for solving Rotate Captcha as an object. 1546 | * @param {string} params.body Base64-encoded image of the captcha that needs to be rotated. 1547 | * @param {number} params.angle Angle to which the captcha needs to be rotated to solve it correctly. Value between `0` to `360`. 1548 | * @param {string} params.textinstructions Optional param. Text instruction that will be shown to worker to help solve the captcha correctly. 1549 | * @param {string} params.imginstructions Optional param. Base64-encoded image instruction that will be shown to worker to help solve the captcha correctly. 1550 | * @param {string} params.lang Optional param. Language code for worker to use while solving the captcha. 1551 | * @param {string} params.pingback Optional param. URL for pingback (callback) response when captcha is solved. 1552 | * 1553 | * @returns {Promise} The result from the solve. 1554 | * @throws APIError 1555 | * 1556 | * @example 1557 | * solver.rotate({ 1558 | * body: "iVBORw0KGgoAAAANSUhEUgAAAcIA...", 1559 | * angle: 15, 1560 | * textinstructions: "Rotate the object to the correct position" 1561 | * }) 1562 | * .then((res) => { 1563 | * console.log(res); 1564 | * }) 1565 | * .catch((err) => { 1566 | * console.log(err); 1567 | * }) 1568 | */ 1569 | public async rotate(params: paramsRotateCaptcha): Promise { 1570 | checkCaptchaParams(params, "rotatecaptcha"); 1571 | 1572 | const payload = { 1573 | ...params, 1574 | method: "rotatecaptcha", 1575 | ...this.defaultPayload, 1576 | }; 1577 | 1578 | const URL = this.in; 1579 | const response = await fetch(URL, { 1580 | body: utils.toFormData(payload), 1581 | method: "post", 1582 | }); 1583 | const result = await response.text(); 1584 | 1585 | let data; 1586 | try { 1587 | data = JSON.parse(result); 1588 | } catch { 1589 | throw new APIError(result); 1590 | } 1591 | 1592 | if (data.status == 1) { 1593 | return this.pollResponse(data.request); 1594 | } else { 1595 | throw new APIError(data.request); 1596 | } 1597 | } 1598 | 1599 | /** 1600 | * ### Solves a KeyCaptcha. 1601 | * 1602 | * This method can be used to solve a KeyCaptcha. It is mostly used to bypass captchas that use KeyCaptcha technology. 1603 | * [Read more about KeyCaptcha Method](https://solvecaptcha.com/solvecaptcha-api#solving_keycaptcha). 1604 | * 1605 | * @param {{ pageurl, userId, sessionId, webServerSign, webServerSign2, pingback, proxy, proxytype }} params Parameters for solving KeyCaptcha as an object. 1606 | * @param {string} params.pageurl The URL where the captcha is located. 1607 | * @param {string} params.userId Value of `s_s_c_user_id` parameter you found on page. 1608 | * @param {string} params.sessionId Value of `s_s_c_session_id` parameter you found on page. 1609 | * @param {string} params.webServerSign Value of `s_s_c_web_server_sign` parameter you found on page. 1610 | * @param {string} params.webServerSign2 Value of `s_s_c_web_server_sign2` parameter you found on page. 1611 | * @param {string} [params.pingback] Optional param. URL for pingback (callback) response when captcha is solved. 1612 | * @param {string} [params.proxy] Optional param. Proxy to use while solving the captcha. Format: `login:password@123.123.123.123:3128`. 1613 | * @param {string} [params.proxytype] Optional param. Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 1614 | * 1615 | * @returns {Promise} The result from the solve. 1616 | * @throws APIError 1617 | * 1618 | * @example 1619 | * solver.keyCaptcha({ 1620 | * pageurl: "https://solvecaptcha.com/demo/keycaptcha", 1621 | * userId: "184015", 1622 | * sessionId: "11975dc265ce9174a54edb1619af15b7", 1623 | * webServerSign: "73ef77fd3cf0ce02947d9088bdc8412a", 1624 | * webServerSign2: "93836d9e7007f38f072ce07d89bb7e2b" 1625 | * }) 1626 | * .then((res) => { 1627 | * console.log(res); 1628 | * }) 1629 | * .catch((err) => { 1630 | * console.log(err); 1631 | * }) 1632 | */ 1633 | public async keyCaptcha(params: paramsKeyCaptcha): Promise { 1634 | params = await renameParams(params); 1635 | checkCaptchaParams(params, "keycaptcha"); 1636 | 1637 | const payload = { 1638 | ...params, 1639 | method: "keycaptcha", 1640 | ...this.defaultPayload, 1641 | }; 1642 | 1643 | const URL = this.in; 1644 | const response = await fetch(URL, { 1645 | body: utils.toFormData(payload), 1646 | method: "post", 1647 | }); 1648 | const result = await response.text(); 1649 | 1650 | let data; 1651 | try { 1652 | data = JSON.parse(result); 1653 | } catch { 1654 | throw new APIError(result); 1655 | } 1656 | 1657 | if (data.status == 1) { 1658 | return this.pollResponse(data.request); 1659 | } else { 1660 | throw new APIError(data.request); 1661 | } 1662 | } 1663 | 1664 | /** 1665 | * ### Solves a Tencent. 1666 | * 1667 | * Use this method to solve Tencent captcha. Returns a token. 1668 | * [Read more about Tencent Method](https://solvecaptcha.com/solvecaptcha-api#tencent). 1669 | * 1670 | * @param {{ pageurl, appId, pingback, proxy, proxytype }} params Parameters for solving Tencent as an object. 1671 | * @param {string} params.pageurl The URL where the captcha is located. 1672 | * @param {string} params.appId The value of `appId` parameter in the website source code. 1673 | * @param {string} [params.pingback] Optional param. URL for pingback (callback) response when captcha is solved. 1674 | * @param {string} [params.proxy] Optional param. Proxy to use while solving the captcha. Format: `login:password@123.123.123.123:3128`. 1675 | * @param {string} [params.proxytype] Optional param. Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 1676 | * 1677 | * @returns {Promise} The result from the solve. 1678 | * @throws APIError 1679 | * 1680 | * @example 1681 | * solver.tencent({ 1682 | * pageurl: "https://mysite.com/page/with/tencent", 1683 | * appId: "189956587" 1684 | * }) 1685 | * .then((res) => { 1686 | * console.log(res); 1687 | * }) 1688 | * .catch((err) => { 1689 | * console.log(err); 1690 | * }) 1691 | */ 1692 | public async tencent(params: paramsTencent): Promise { 1693 | params = await renameParams(params); 1694 | checkCaptchaParams(params, "tencent"); 1695 | 1696 | const payload = { 1697 | ...params, 1698 | method: "tencent", 1699 | ...this.defaultPayload, 1700 | }; 1701 | 1702 | const URL = this.in; 1703 | const response = await fetch(URL, { 1704 | body: utils.toFormData(payload), 1705 | method: "post", 1706 | }); 1707 | const result = await response.text(); 1708 | 1709 | let data; 1710 | try { 1711 | data = JSON.parse(result); 1712 | } catch { 1713 | throw new APIError(result); 1714 | } 1715 | 1716 | if (data.status == 1) { 1717 | return this.pollResponse(data.request); 1718 | } else { 1719 | throw new APIError(data.request); 1720 | } 1721 | } 1722 | 1723 | /** 1724 | * ### Solves a atbCAPTCHA. 1725 | * 1726 | * Use this method to solve atbCAPTCHA captcha. Returns a token. 1727 | * [Read more about atbCAPTCHA Method](https://solvecaptcha.com/solvecaptcha-api#atb-captcha). 1728 | * 1729 | * @param {{ pageurl, appId, apiServer, pingback, proxy, proxytype }} params Parameters for solving atbCAPTCHA as an object. 1730 | * @param {string} params.pageurl The URL where the captcha is located. 1731 | * @param {string} params.appId The value of `appId` parameter in the website source code. 1732 | * @param {string} params.apiServer The value of `apiServer` parameter in the website source code. 1733 | * @param {string} [params.pingback] Optional param. URL for pingback (callback) response when captcha is solved. 1734 | * @param {string} [params.proxy] Optional param. Proxy to use while solving the captcha. Format: `login:password@123.123.123.123:3128`. 1735 | * @param {string} [params.proxytype] Optional param. Type of your proxy: `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`. 1736 | * 1737 | * @returns {Promise} The result from the solve. 1738 | * @throws APIError 1739 | * 1740 | * @example 1741 | * solver.atbCaptcha({ 1742 | * pageurl: "https://mysite.com/page/with/tencent", 1743 | * appId: "af25e409b33d722a95e56a230ff8771c", 1744 | apiServer: "https://cap.aisecurius.com" 1745 | * }) 1746 | * .then((res) => { 1747 | * console.log(res); 1748 | * }) 1749 | * .catch((err) => { 1750 | * console.log(err); 1751 | * }) 1752 | */ 1753 | public async atbCaptcha(params: paramsAtbCaptcha): Promise { 1754 | params = await renameParams(params); 1755 | checkCaptchaParams(params, "atb_captcha"); 1756 | 1757 | const payload = { 1758 | ...params, 1759 | method: "atb_captcha", 1760 | ...this.defaultPayload, 1761 | }; 1762 | 1763 | const URL = this.in; 1764 | const response = await fetch(URL, { 1765 | body: utils.toFormData(payload), 1766 | method: "post", 1767 | }); 1768 | const result = await response.text(); 1769 | 1770 | let data; 1771 | try { 1772 | data = JSON.parse(result); 1773 | } catch { 1774 | throw new APIError(result); 1775 | } 1776 | 1777 | if (data.status == 1) { 1778 | return this.pollResponse(data.request); 1779 | } else { 1780 | throw new APIError(data.request); 1781 | } 1782 | } 1783 | 1784 | /** 1785 | * ### Method for solving Audio captcha. 1786 | * 1787 | * Use the following method to bypass an audio captcha (`mp3` formats only). You must provide the language as `lang = 'en'`. Supported languages are "en", "ru", "de", "el", "pt", "fr". 1788 | * [Read more about Audio recognition Method](https://solvecaptcha.com/solvecaptcha-api#audio-recognition). 1789 | * 1790 | * @param {{ body, lang, pingback }} params Object containing parameters for the audio captcha. 1791 | * @param {string} params.body Base64 encoded audio file in `mp3` format. Max file size: 1 MB. 1792 | * @param {string} params.lang The language of audio record. Supported languages are: "en", "ru", "de", "el", "pt", "fr". 1793 | * @param {string} [params.pingback] URL for pingback response once captcha is solved. 1794 | * 1795 | * @returns {Promise} The result from solving the audio captcha. 1796 | * @throws APIError 1797 | * @example 1798 | * solver.audio({ 1799 | * body: "SUQzBAAAAAAAHFRTU0UAAAA...", 1800 | * lang: "en" 1801 | * }) 1802 | * .then((res) => { 1803 | * console.log(res); 1804 | * }) 1805 | * .catch((err) => { 1806 | * console.log(err); 1807 | * }) 1808 | */ 1809 | public async audio(params: paramsAudioCaptcha): Promise { 1810 | checkCaptchaParams(params, "audio"); 1811 | 1812 | const payload = { 1813 | ...params, 1814 | method: "audio", 1815 | ...this.defaultPayload, 1816 | }; 1817 | 1818 | const response = await fetch(this.in, { 1819 | method: "post", 1820 | body: utils.toFormData(payload), 1821 | }); 1822 | 1823 | const result = await response.text(); 1824 | 1825 | let data; 1826 | try { 1827 | data = JSON.parse(result); 1828 | } catch { 1829 | throw new APIError(result); 1830 | } 1831 | 1832 | if (data.status == 1) { 1833 | return this.pollResponse(data.request); 1834 | } else { 1835 | throw new APIError(data.request); 1836 | } 1837 | } 1838 | 1839 | /** 1840 | * Reports a captcha as correctly solved. 1841 | * 1842 | * @param {string} id The ID of the captcha 1843 | * @throws APIError 1844 | * @example 1845 | * solver.goodReport("7031854546") 1846 | * 1847 | */ 1848 | public async goodReport(id: string): Promise { 1849 | const payload = { 1850 | id: id, 1851 | action: "reportgood", 1852 | ...this.defaultPayload, 1853 | }; 1854 | 1855 | const response = await fetch(this.res + utils.objectToURI(payload)); 1856 | const result = await response.text(); 1857 | 1858 | let data; 1859 | try { 1860 | data = JSON.parse(result); 1861 | } catch { 1862 | throw new APIError(result); 1863 | } 1864 | 1865 | if (data.request == "OK_REPORT_RECORDED") { 1866 | return data.request; 1867 | } else { 1868 | throw new APIError(data.request); 1869 | } 1870 | } 1871 | 1872 | /** 1873 | * Report an unsuccessful solve 1874 | * 1875 | * @param {string} id The id of the captcha solve 1876 | * 1877 | * @returns {Promise} Resolves on completion 1878 | * @throws APIError 1879 | * @example 1880 | * solver.badReport("7031854546") 1881 | */ 1882 | public async badReport(id: string): Promise { 1883 | const payload = { 1884 | id: id, 1885 | action: "reportbad", 1886 | ...this.defaultPayload, 1887 | }; 1888 | 1889 | const response = await fetch(this.res + utils.objectToURI(payload)); 1890 | const result = await response.text(); 1891 | 1892 | let data; 1893 | try { 1894 | data = JSON.parse(result); 1895 | } catch { 1896 | throw new APIError(result); 1897 | } 1898 | 1899 | if ( 1900 | data.request == "OK_REPORT_RECORDED" || 1901 | data.request == "ERROR_DUPLICATE_REPORT" 1902 | ) { 1903 | return data.request; 1904 | } else { 1905 | throw new APIError(data.request); 1906 | } 1907 | } 1908 | } 1909 | --------------------------------------------------------------------------------