Una extensión de VS Code diseñada para el desarrollo de CaptchaAI puede acelerar su flujo de trabajo: detectar claves de sitio en el código, probar soluciones desde el editor, mostrar su saldo en la barra de estado e insertar fragmentos de código para patrones API comunes.
Funciones de extensión
| Característica | Qué hace |
|---|---|
| Barra de estado del saldo | Muestra el saldo actual de CaptchaAI de un vistazo |
| comando resolver | Envíe una solución CAPTCHA directamente desde VS Code |
| Detección de claves de sitio | Resalte y extraiga claves de sitio de archivos abiertos |
| Fragmentos de código | Insertar texto estándar para llamadas API reCAPTCHA, Turnstile y hCaptcha |
| búsqueda de errores | Pase el cursor sobre los códigos de error para ver las descripciones |
Estructura de extensión
captchaai-vscode/
├── package.json
├── src/
│ └── extension.js
├── snippets/
│ ├── python.json
│ └── javascript.json
└── README.md
paquete.json
{
"name": "captchaai-dev-tools",
"displayName": "CaptchaAI Dev Tools",
"description": "CaptchaAI API development tools for VS Code",
"version": "1.0.0",
"engines": { "vscode": "^1.80.0" },
"categories": ["Snippets", "Other"],
"activationEvents": ["onStartupFinished"],
"main": "./src/extension.js",
"contributes": {
"commands": [
{
"command": "captchaai.checkBalance",
"title": "CaptchaAI: Check Balance"
},
{
"command": "captchaai.solveRecaptcha",
"title": "CaptchaAI: Solve reCAPTCHA v2"
},
{
"command": "captchaai.solveTurnstile",
"title": "CaptchaAI: Solve Turnstile"
},
{
"command": "captchaai.detectSitekey",
"title": "CaptchaAI: Detect Sitekey in File"
}
],
"configuration": {
"title": "CaptchaAI",
"properties": {
"captchaai.apiKey": {
"type": "string",
"default": "",
"description": "Your CaptchaAI API key"
},
"captchaai.showBalance": {
"type": "boolean",
"default": true,
"description": "Show balance in status bar"
},
"captchaai.pollInterval": {
"type": "number",
"default": 5,
"description": "Poll interval in seconds"
}
}
},
"snippets": [
{
"language": "python",
"path": "./snippets/python.json"
},
{
"language": "javascript",
"path": "./snippets/javascript.json"
}
]
}
}
Implementación de extensión
// src/extension.js
const vscode = require("vscode");
const API_BASE = "https://ocr.captchaai.com";
function getApiKey() {
const config = vscode.workspace.getConfiguration("captchaai");
const key = config.get("apiKey");
if (!key) {
vscode.window.showErrorMessage(
"CaptchaAI: Set your API key in Settings → CaptchaAI"
);
return null;
}
return key;
}
// --- Balance Status Bar ---
let balanceStatusBar;
let balanceInterval;
async function updateBalance() {
const key = getApiKey();
if (!key) return;
try {
const url = new URL(`${API_BASE}/res.php`);
url.searchParams.set("key", key);
url.searchParams.set("action", "getbalance");
url.searchParams.set("json", "1");
const response = await fetch(url);
const result = await response.json();
if (result.status === 1) {
const balance = parseFloat(result.request).toFixed(2);
balanceStatusBar.text = `$(credit-card) CaptchaAI: $${balance}`;
balanceStatusBar.tooltip = `CaptchaAI Balance: $${balance}`;
} else {
balanceStatusBar.text = "$(warning) CaptchaAI: Error";
}
} catch {
balanceStatusBar.text = "$(warning) CaptchaAI: Offline";
}
}
// --- Solve Command ---
async function solveCaptcha(method, extraFields) {
const key = getApiKey();
if (!key) return;
const sitekey = await vscode.window.showInputBox({
prompt: "Enter the CAPTCHA sitekey",
placeHolder: "6LeIxAcTAAAAAJcZ...",
});
if (!sitekey) return;
const pageurl = await vscode.window.showInputBox({
prompt: "Enter the page URL",
placeHolder: "https://example.com",
});
if (!pageurl) return;
const params = {
key,
method,
pageurl,
json: 1,
...extraFields,
};
if (method === "userrecaptcha") {
params.googlekey = sitekey;
} else {
params.sitekey = sitekey;
}
// Submit
vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: "CaptchaAI: Solving...",
cancellable: true,
},
async (progress, cancellation) => {
try {
const submitResponse = await fetch(`${API_BASE}/in.php`, {
method: "POST",
body: new URLSearchParams(params),
});
const submitResult = await submitResponse.json();
if (submitResult.status !== 1) {
vscode.window.showErrorMessage(
`CaptchaAI: ${submitResult.request || "Submit failed"}`
);
return;
}
const taskId = submitResult.request;
progress.report({ message: `Task ${taskId} submitted` });
// Poll
const config = vscode.workspace.getConfiguration("captchaai");
const interval = config.get("pollInterval") * 1000;
for (let i = 0; i < 60; i++) {
if (cancellation.isCancellationRequested) return;
await new Promise((r) => setTimeout(r, interval));
const pollUrl = new URL(`${API_BASE}/res.php`);
pollUrl.searchParams.set("key", key);
pollUrl.searchParams.set("action", "get");
pollUrl.searchParams.set("id", taskId);
pollUrl.searchParams.set("json", "1");
const pollResponse = await fetch(pollUrl);
const pollResult = await pollResponse.json();
if (pollResult.request === "CAPCHA_NOT_READY") {
progress.report({ message: `Waiting... (${(i + 1) * (interval / 1000)}s)` });
continue;
}
if (pollResult.status === 1) {
const token = pollResult.request;
// Copy to clipboard
await vscode.env.clipboard.writeText(token);
vscode.window.showInformationMessage(
`CaptchaAI: Solved! Token copied to clipboard (${token.length} chars)`
);
// Also insert at cursor if editor is active
const editor = vscode.window.activeTextEditor;
if (editor) {
const action = await vscode.window.showQuickPick(
["Copy only", "Insert at cursor"],
{ placeHolder: "Token copied. Insert into editor?" }
);
if (action === "Insert at cursor") {
editor.edit((editBuilder) => {
editBuilder.insert(editor.selection.active, token);
});
}
}
return;
}
vscode.window.showErrorMessage(
`CaptchaAI: ${pollResult.request || "Solve failed"}`
);
return;
}
vscode.window.showErrorMessage("CaptchaAI: Solve timed out");
} catch (err) {
vscode.window.showErrorMessage(`CaptchaAI: ${err.message}`);
}
}
);
}
// --- Sitekey Detection ---
async function detectSitekey() {
const editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showWarningMessage("No active editor");
return;
}
const text = editor.document.getText();
const patterns = [
{ regex: /data-sitekey=["']([^"']+)["']/g, type: "HTML data-sitekey" },
{ regex: /googlekey['":\s]+["']([a-zA-Z0-9_-]{40})["']/g, type: "API googlekey" },
{ regex: /sitekey['":\s]+["']([a-zA-Z0-9_-]{20,})["']/g, type: "sitekey parameter" },
{ regex: /render=([a-zA-Z0-9_-]{40})/g, type: "reCAPTCHA render" },
];
const found = [];
for (const { regex, type } of patterns) {
let match;
while ((match = regex.exec(text)) !== null) {
found.push({ key: match[1], type, position: match.index });
}
}
if (found.length === 0) {
vscode.window.showInformationMessage("No sitekeys found in current file");
return;
}
const items = found.map((f) => ({
label: f.key,
description: f.type,
detail: `Position: ${f.position}`,
key: f.key,
}));
const selected = await vscode.window.showQuickPick(items, {
placeHolder: `Found ${found.length} sitekey(s) — select to copy`,
});
if (selected) {
await vscode.env.clipboard.writeText(selected.key);
vscode.window.showInformationMessage(`Sitekey copied: ${selected.key}`);
}
}
// --- Activation ---
function activate(context) {
// Balance status bar
const config = vscode.workspace.getConfiguration("captchaai");
if (config.get("showBalance")) {
balanceStatusBar = vscode.window.createStatusBarItem(
vscode.StatusBarAlignment.Right,
100
);
balanceStatusBar.command = "captchaai.checkBalance";
balanceStatusBar.text = "$(credit-card) CaptchaAI";
balanceStatusBar.show();
updateBalance();
balanceInterval = setInterval(updateBalance, 300000); // Every 5 minutes
context.subscriptions.push(balanceStatusBar);
}
// Register commands
context.subscriptions.push(
vscode.commands.registerCommand("captchaai.checkBalance", async () => {
await updateBalance();
vscode.window.showInformationMessage(balanceStatusBar.tooltip);
}),
vscode.commands.registerCommand("captchaai.solveRecaptcha", () => {
solveCaptcha("userrecaptcha", {});
}),
vscode.commands.registerCommand("captchaai.solveTurnstile", () => {
solveCaptcha("turnstile", {});
}),
vscode.commands.registerCommand("captchaai.detectSitekey", detectSitekey)
);
}
function deactivate() {
if (balanceInterval) clearInterval(balanceInterval);
}
module.exports = { activate, deactivate };
package.json mínimo para la extensión
{
"contributes": {
"commands": [
{ "command": "captchaai.solveRecaptcha", "title": "CaptchaAI: Solve reCAPTCHA" },
{ "command": "captchaai.solveTurnstile", "title": "CaptchaAI: Solve Turnstile" },
{ "command": "captchaai.detectSitekey", "title": "CaptchaAI: Detect Sitekey" }
],
"configuration": {
"title": "CaptchaAI",
"properties": {
"captchaai.apiKey": { "type": "string" },
"captchaai.pollInterval": { "type": "number", "default": 5 }
}
}
}
}
Fragmentos de código
Fragmentos de Python
{
"CaptchaAI reCAPTCHA v2": {
"prefix": "cai-recaptcha-v2",
"body": [
"import requests",
"",
"# Submit reCAPTCHA v2 task",
"response = requests.post(",
" \"https://ocr.captchaai.com/in.php\",",
" data={",
" \"key\": \"${1:YOUR_API_KEY}\",",
" \"method\": \"userrecaptcha\",",
" \"googlekey\": \"${2:SITE_KEY}\",",
" \"pageurl\": \"${3:https://example.com}\",",
" \"json\": 1,",
" },",
")",
"task_id = response.json()[\"request\"]",
"",
"# Poll for result",
"import time",
"while True:",
" time.sleep(5)",
" result = requests.get(",
" \"https://ocr.captchaai.com/res.php\",",
" params={\"key\": \"${1}\", \"action\": \"get\", \"id\": task_id, \"json\": 1},",
" ).json()",
" if result[\"request\"] != \"CAPCHA_NOT_READY\":",
" token = result[\"request\"]",
" break"
],
"description": "CaptchaAI reCAPTCHA v2 solve"
},
"CaptchaAI Turnstile": {
"prefix": "cai-turnstile",
"body": [
"import requests",
"",
"response = requests.post(",
" \"https://ocr.captchaai.com/in.php\",",
" data={",
" \"key\": \"${1:YOUR_API_KEY}\",",
" \"method\": \"turnstile\",",
" \"sitekey\": \"${2:SITE_KEY}\",",
" \"pageurl\": \"${3:https://example.com}\",",
" \"json\": 1,",
" },",
")",
"task_id = response.json()[\"request\"]"
],
"description": "CaptchaAI Turnstile solve"
},
"CaptchaAI Balance Check": {
"prefix": "cai-balance",
"body": [
"import requests",
"",
"balance = requests.get(",
" \"https://ocr.captchaai.com/res.php\",",
" params={\"key\": \"${1:YOUR_API_KEY}\", \"action\": \"getbalance\", \"json\": 1},",
").json()",
"print(f\"Balance: \\${balance['request']}\")"
],
"description": "CaptchaAI balance check"
}
}
Fragmentos de JavaScript
{
"CaptchaAI reCAPTCHA v2": {
"prefix": "cai-recaptcha-v2",
"body": [
"const response = await fetch('https://ocr.captchaai.com/in.php', {",
" method: 'POST',",
" body: new URLSearchParams({",
" key: '${1:YOUR_API_KEY}',",
" method: 'userrecaptcha',",
" googlekey: '${2:SITE_KEY}',",
" pageurl: '${3:https://example.com}',",
" json: 1,",
" }),",
"});",
"const { request: taskId } = await response.json();",
"",
"// Poll for result",
"let token;",
"while (true) {",
" await new Promise(r => setTimeout(r, 5000));",
" const url = new URL('https://ocr.captchaai.com/res.php');",
" url.searchParams.set('key', '${1}');",
" url.searchParams.set('action', 'get');",
" url.searchParams.set('id', taskId);",
" url.searchParams.set('json', '1');",
" const result = await (await fetch(url)).json();",
" if (result.request !== 'CAPCHA_NOT_READY') {",
" token = result.request;",
" break;",
" }",
"}"
],
"description": "CaptchaAI reCAPTCHA v2 solve"
}
}
Solución de problemas
| Problema | causa | Solución |
|---|---|---|
| El saldo muestra "Sin conexión" | No se puede acceder a la API desde VS Code | Verifique la red/firewall; asegúrese de que ocr.captchaai.com sea accesible |
| Error "Establezca su clave API" | Clave no configurada | Configuración → buscar "CaptchaAI" → ingresar clave API |
| Los fragmentos no aparecen | Modo de idioma incorrecto | Verifique que el modo de idioma del archivo coincida con el fragmento (Python/JavaScript) |
| Resolver tiempos de espera | Tarea fallida o red lenta | Aumentar el intervalo de consulta en la configuración; verificar la clave del sitio y la URL de la página |
| La detección de Sitekey no encuentra nada | No hay patrones coincidentes en el archivo | Verifique que el archivo contenga atributos data-sitekey, googlekey o sitekey |
Preguntas frecuentes
¿Esta extensión está disponible en VS Code Marketplace?
Esta guía muestra cómo construir la extensión. Para publicar sigue elGuía de publicación de extensiones de código VS. También puedes usar la extensión localmente a través de code --install-extension captchaai-dev-tools-1.0.0.vsix.
¿La extensión almacena mi clave API de forma segura?
La configuración de VS Code se almacena en JSON en el disco. Para mayor seguridad, use la API SecretStorage de VS Code para almacenar la clave en el llavero del sistema operativo en lugar de la configuración de texto sin formato.
¿Puedo agregar prefijos de fragmentos personalizados?
Sí, edite los archivos JSON de fragmentos en la carpeta snippets/. Cada fragmento tiene un campo prefix que activa la sugerencia de autocompletar.
Artículos relacionados
- Seguridad de clave API de lista blanca de IP Captchaai
- Comparación de la nube Captchaai Vs Capmonster
- Captchaai Webhooks versus consultas
Próximos pasos
Cree herramientas CaptchaAI directamente en su editor:obtenga su clave APIy empezar a desarrollar.
Guías relacionadas: