{"id":20050156,"url":"https://github.com/2captcha/custom-slider-demo","last_synced_at":"2026-05-13T14:31:41.112Z","repository":{"id":227690335,"uuid":"771809589","full_name":"2captcha/custom-slider-demo","owner":"2captcha","description":"Slide Captcha Solver, Bypass Techniques","archived":false,"fork":false,"pushed_at":"2024-08-09T12:51:45.000Z","size":42,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-29T10:59:26.135Z","etag":null,"topics":["bypass-slider-captcha","captcha-slider-puzzle","slide-captcha-solver","slide-to-verify-captcha","slider-captcha","slider-captcha-solver"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/2captcha.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-03-14T01:44:13.000Z","updated_at":"2025-04-07T17:27:11.000Z","dependencies_parsed_at":"2024-03-14T18:17:55.906Z","dependency_job_id":"ecc9bd21-0ae6-4080-b800-81693f33183b","html_url":"https://github.com/2captcha/custom-slider-demo","commit_stats":null,"previous_names":["2captcha/custom-slider-demo"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/2captcha/custom-slider-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/2captcha%2Fcustom-slider-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/2captcha%2Fcustom-slider-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/2captcha%2Fcustom-slider-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/2captcha%2Fcustom-slider-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/2captcha","download_url":"https://codeload.github.com/2captcha/custom-slider-demo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/2captcha%2Fcustom-slider-demo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32986712,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"ssl_error","status_checked_at":"2026-05-13T13:14:51.610Z","response_time":115,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bypass-slider-captcha","captcha-slider-puzzle","slide-captcha-solver","slide-to-verify-captcha","slider-captcha","slider-captcha-solver"],"created_at":"2024-11-13T11:54:37.493Z","updated_at":"2026-05-13T14:31:41.096Z","avatar_url":"https://github.com/2captcha.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Custom Slider Captcha Demo\n\nThis demo code is made to demonstrate how 2Captcha API can be used to bypass custom slider captchas.\n\n\n## Concept\nTo solve the custom slider captcha we need to calculate the path where we should drag the slider. In most cases all we need is just two points: start and end, and the start point is usually static, so we can find it just once. The second point can be found by human workers of 2Captcha, we can show them an image and provide instructions describing which exact point they need to indicate, they will click the point and 2Captcha API will return the coordinates of this point. The API method we need is [Coordinates](https://2captcha.com/api-docs/coordinates).\n\n## Approach\n\nTo interact with the captcha we must use a browser and a framework that allows us to control the browser. In this example, we'll use [Puppeteer](https://pptr.dev/) as a browser automation framework. And we'll also use [@2captcha/captcha-solver](https://www.npmjs.com/package/@2captcha/captcha-solver) to interact with 2Captcha API.\n\n### Prepare the environment\n\nInstall the dependencies:\n\n```sh\nyarn add puppeteer @2captcha/captcha-solver\n```\n\nSet the API key as an environment variable:\n\n```sh\nexport APIKEY=your_api_key_here\n```\n\n### Code\n\nAs we use ES6 `import` statements in the code, let's add the following property to the `package.json` file:\n\n```json\n\"type\": \"module\"\n```\n\nCreate a file named `index.js` and let's start to add some code:\n\nFirst of all, let's import the dependencies\n\n```js\nimport puppeteer from 'puppeteer'\nimport { Solver } from '@2captcha/captcha-solver'\nimport { readFile } from 'node:fs/promises'\n```\n\nThen let's create a new instance of `Solver` with our API key\n\n```js\nconst solver = new Solver(process.env.APIKEY)\n```\n\nWe'll need to generate some random numbers, so let's add a simple one-liner that will do that job:\n\n```js\nconst randomInt = (min, max) =\u003e Math.floor(Math.random() * (max - min + 1)) + min;\n```\n\nThe rest of the code will be wrapped into a self-executing async function as it's much more convenient to call all Promise-based Puppeeter methods with `async/await`.\n\n```js\n(async () =\u003e {\n // the rest of the code\n})();\n```\n\nLet's launch a browser, get the opened tab and open the captcha demo page. We also define a variable `success` that will hold the captcha bypass process state.\n\n```js\nconst browser = await puppeteer.launch({\n    devtools: true,\n    slowMo: 11\n})\nconst [page] = await browser.pages()\n\nawait page.goto('https://www.jqueryscript.net/demo/image-puzzle-slider-captcha/')\n\nlet success = false\n```\n\nThere's never a 100% guarantee that we'll bypass the captcha from the 1st attempt, so let's start a loop. We'll exit the loop once the captcha is successfully solved.\n\nThe demo page shows a cookies consent modal window for some countries, so let's decline all cookies if the page asks us about it.\n\nLet's also load the instruction image that will be shown to 2Captcha workers.\n\n```js\nwhile (!success) {\n    try {\n        const consentButton = await page.waitForSelector('body \u003e div.fc-consent-root \u003e div.fc-dialog-container \u003e div.fc-dialog.fc-choice-dialog \u003e div.fc-footer-buttons-container \u003e div.fc-footer-buttons \u003e button.fc-button.fc-cta-do-not-consent.fc-secondary-button', { timeout: 3000 })\n        if (consentButton) consentButton.click()\n    } catch (e) { }\n\n    const instruction = await readFile('./imginstructions.png', { encoding: 'base64' })\n```\n\nThen we need to grab the captcha image and send it to 2Captcha API using the [Coordinates](https://2captcha.com/api-docs/coordinates) method. There's a chance that the image will fail to load, so we check the length of the data URL returned.\n\nOnce we have the image, we pass it to the corresponding method of the `Solver` instance.\nThe result contains an array of point coordinates. In our case, there should be only one point. We use its `x` coordinate as a distance between the left image border and the center of the target puzzle piece.\n\n```js\nconst img = await page.evaluate(() =\u003e document.querySelector('canvas').toDataURL())\nif (img.length \u003c 2000) return\n\ntry {\n    const res = await solver.coordinates({\n        body: img,\n        textinstructions: 'Puzzle center | Центр пазла',\n        imginstructions: instruction\n    })\n    const offset = res.data[0].x       \n```\n\n\nThen we get the slider element and its coordinates and dimensions. We'll use its center as a starting point for our drag-and-drop action.\n\n```js\nconst slider = await page.$('div.slider')\n\nconst bb = await slider.boundingBox()\n\nconst init = {\n    x: bb.x + bb.width / 2,\n    y: bb.y + bb.height / 2\n}\n```\n\nThen we calculate the coordinates of the final point:\nIn our case the width of the square part of the puzzle piece is 40px, so we need to subtract half of it, as we expect to receive the center of the puzzle piece. We also use the `y` coordinate received just to avoid moving the pointer only horizontally, as we know that the captcha is tracking the path.\n\n```js\nconst target = {\n    x: bb.x + bb.width / 2 + parseFloat(offset) - 20,\n    y: res.data[0].y\n}\n```\n\nOptionally we can draw a small box on the image to see the exact point clicked by the 2Captcha worker\n\n```js\nawait page.evaluate((coord) =\u003e {\n    console.log(coord)\n    const canvas = document.querySelector('#captcha \u003e canvas')\n    let ctx = canvas.getContext('2d')\n    ctx.globalAlpha = 1\n    ctx.fillStyle = 'red'\n    ctx.fillRect(coord.x, coord.y, 3, 3)\n}, {\n    x: parseInt(res.data[0].x),\n    y: parseInt(res.data[0].y)\n})\n```\n\nThen we move the mouse pointer to the start point, click and hold the mouse button and move the pointer to the end point. When moving the slider we provide a random number of steps to make the path more complex because the captcha is tracking the mouse events.\n\n```js\nawait page.mouse.move(init.x, init.y)\nawait page.mouse.down()\nawait page.mouse.move(target.x, target.y, {\n    steps: randomInt(50, 100)\n})\nawait page.mouse.up()\n```\n\nFinally, we are trying to understand if we were able to bypass the captcha. In our case after the solution we are redirected to another page, so we are waiting for navigation. In the case of a successful solution, we exit the loop setting the `success` variable to `true`, [reporting a correct answer](https://2captcha.com/api-docs/report-correct) to 2Captcha API, making a screenshot and closing the page and browser. In case of error (no navigation within 5 seconds) we [report an incorrect answer](https://2captcha.com/api-docs/report-incorrect) and make one more attempt to solve the captcha.\n\n```js\ntry {\n    await page.waitForNavigation({ timeout: 5000 })\n    success = true\n    await solver.goodReport(res.id)\n    await page.screenshot({\n        path: 'screenshot.png'\n    })\n    await new Promise(ok =\u003e setTimeout(() =\u003e ok(), 5000))\n    await page.close()\n    await browser.close()\n} catch (e) {\n    await solver.badReport(res.id)\n}\n```\n\nAs you may have noticed, the code starting from interaction with 2Captcha API is wrapped into a `try/catch` block, so we need to close this block with the `catch` as well as close our loop here.\n\n```js\n    } catch (e) {\n        console.log(`Failed to solve the captcha: ${e.err}`)\n    }\n}\n```\n\n### Using this demo\n\nYou can just clone the repo, install  the dependencies and run it:\n\n```sh\ngit clone git@github.com:2captcha/custom-slider-demo.git\nyarn #or npm i\nyarn start #or npm start\n```\n\nThat's it, folks!\n\n## License\n\nThe code in this repository is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more details.\n\n### Graphics and Trademarks\n\nThe graphics and trademarks included in this repository are not covered by the MIT License. Please contact \u003ca href=\"mailto:support@2captcha.com\"\u003esupport\u003c/a\u003e for permissions regarding the use of these materials.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F2captcha%2Fcustom-slider-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F2captcha%2Fcustom-slider-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F2captcha%2Fcustom-slider-demo/lists"}