Skip to content

Instantly share code, notes, and snippets.

@fipso
Created July 19, 2025 21:33
Show Gist options
  • Save fipso/4a8fe5166ca95ab56d3272e5e32c9eb8 to your computer and use it in GitHub Desktop.
Save fipso/4a8fe5166ca95ab56d3272e5e32c9eb8 to your computer and use it in GitHub Desktop.
// ==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