Created
July 19, 2025 21:33
-
-
Save fipso/4a8fe5166ca95ab56d3272e5e32c9eb8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Auto CutCaptcha Solver with 2Captcha | |
| // @namespace https://2captcha.com/ | |
| // @version 1.0 | |
| // @description Automatically solves CutCaptcha using 2Captcha API | |
| // @match *://*/* | |
| // @grant GM.xmlHttpRequest | |
| // ==/UserScript== | |
| (async function () { | |
| const API_KEY = ''; // Replace with your actual 2Captcha API key | |
| const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); | |
| await sleep(2000); | |
| // Helper function to mimic fetch using GM.xmlHttpRequest | |
| const gmFetch = (url, options = {}) => { | |
| return new Promise((resolve, reject) => { | |
| GM.xmlHttpRequest({ | |
| method: options.method || 'GET', | |
| url: url, | |
| data: options.body ? JSON.stringify(options.body) : undefined, | |
| headers: options.headers || {}, | |
| onload: (response) => { | |
| if (response.status >= 200 && response.status < 300) { | |
| resolve({ | |
| ok: true, | |
| json: () => Promise.resolve(JSON.parse(response.responseText)), | |
| }); | |
| } else { | |
| reject(new Error(`HTTP error! status: ${response.status}`)); | |
| } | |
| }, | |
| onerror: (error) => { | |
| reject(error); | |
| } | |
| }); | |
| }); | |
| }; | |
| // Detect miseryKey | |
| const miseryKey = CUTCAPTCHA_MISERY_KEY; | |
| if (!miseryKey) return; | |
| console.log("miseryKey", miseryKey); | |
| // Detect apiKey from script src | |
| let apiKey = ''; | |
| const scripts = document.getElementsByTagName('script'); | |
| for (let script of scripts) { | |
| if (script.src && script.src.includes('cutcaptcha')) { | |
| const parts = script.src.split('/'); | |
| apiKey = parts[parts.length - 1].replace('.js', ''); | |
| break; | |
| } | |
| } | |
| if (!apiKey) return; | |
| console.log("apiKey", apiKey); | |
| const pageUrl = window.location.href; | |
| const createTask = async () => { | |
| const res = await gmFetch('https://api.2captcha.com/createTask', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: { | |
| clientKey: API_KEY, | |
| task: { | |
| type: 'CutCaptchaTaskProxyless', | |
| websiteURL: pageUrl, | |
| miseryKey: miseryKey, | |
| apiKey: apiKey | |
| } | |
| } | |
| }); | |
| const data = await res.json(); | |
| if (data.errorId !== 0) throw new Error(data.errorDescription); | |
| console.log("2captcha task", data.taskId); | |
| return data.taskId; | |
| }; | |
| const getToken = async (taskId) => { | |
| for (let i = 0; i < 24; i++) { // Poll for up to 2 minutes | |
| await sleep(5000); | |
| const res = await gmFetch('https://api.2captcha.com/getTaskResult', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: { clientKey: API_KEY, taskId } | |
| }); | |
| const data = await res.json(); | |
| if (data.errorId !== 0) throw new Error(data.errorDescription); | |
| if (data.status === 'ready') return data.solution.token; | |
| } | |
| throw new Error('Timeout: captcha not solved in time'); | |
| }; | |
| let token; | |
| try { | |
| token = await getToken(await createTask()); | |
| } catch (error) { | |
| console.error('Error solving CutCaptcha:', error); | |
| return; | |
| } | |
| // Inject the token | |
| let capTokenInput = document.querySelector('input#cap_token'); | |
| if (!capTokenInput) { | |
| capTokenInput = document.createElement('input'); | |
| capTokenInput.type = 'hidden'; | |
| capTokenInput.id = 'cap_token'; | |
| capTokenInput.name = 'cap_token'; // Assuming name is also cap_token if needed | |
| // Find the form or append to body/form | |
| const form = document.querySelector('form'); // Assume first form or adjust | |
| if (form) form.appendChild(capTokenInput); | |
| } | |
| capTokenInput.value = token; | |
| // Submit the form if exists | |
| const form = capTokenInput.closest('form'); | |
| if (form) form.submit(); | |
| // If callback exists | |
| if (typeof capResponseCallback === 'function') { | |
| capResponseCallback(token); | |
| } | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment