Altcha - Alternative CAPTCHA

Examples of Tasks

There is also an invisible captcha (Invisible Captcha), which has no visible interface on the page and does not require any user actions — verification occurs in the background.

Attention!
Built-in proxies are used by default — their cost is already included in the service. You only need to specify your own proxies in cases where the website does not accept the token or access to the built-in services is restricted.

If you are using a proxy, please use a proxy with username and password authentication.
IMPORTANT: Some parameter values are dynamic — they change with each render of the page using Altcha. Extract them immediately before creating the task to avoid errors during solving.

Request Parameters

ParameterTypeRequiredDescription
type String Required CustomTask
class String Required altcha
websiteURL String Required The main page URL where the Altcha is located.
websiteKey String Required For this task, sending an empty string is allowed.
metadata.challenge String Required Unique task identifier obtained from the website.
metadata.iterations String Required Number of iterations or the maximum number for calculations. Important: the iterations parameter corresponds to the maxnumber value!
metadata.salt String Required Salt obtained from the site, used for hash generation. Important: Always send the full value of the salt field, including all parameters (edk, codeChallenge, expires, etc.).
metadata.signature String Required Digital signature of the request.
userAgent String Optional Browser User-Agent. Pass only a valid UA from Windows OS.
proxyType String Optional http - regular http/https proxy;
https - try this option only if "http" doesn't work;
socks4 - socks4 proxy;
socks5 - socks5 proxy.
proxyAddress String Optional IPv4/IPv6 proxy IP address. Not allowed: transparent proxies or local machine proxies.
proxyPort Integer Optional Proxy port.
proxyLogin String Optional Proxy server login.
proxyPassword String Optional Proxy server password.

Create Task - Without Proxy

Request

POST https://captcha69.com/createTask
Content-Type: application/json

{
  "clientKey": "max1_YOUR_API_KEY",
  "task": {
    "type": "CustomTask",
    "class": "altcha",
    "websiteURL": "https://example.com",
    "websiteKey": "",
    "userAgent": "userAgentPlaceholder",
    "metadata": {
      "challenge": "3dd28253be6cc0c54d95f7f98c517e68744597cc6e66109619d1ac975c39181c",
      "iterations": "5000",
      "salt": "46d5b1c8871e5152d902ee3f?edk=1493462145de1ce33a52fb569b27a364&codeChallenge=464Cjs7PbiJJhJZ_ReJ-y9UGGDndcpsnP6vS8x1nEJyTkhjQkJyL2jcnYEuMKcrG&expires=1761048664",
      "signature": "4b1cf0e0be0f4e5247e50b0f9a449830f1fbca44c32ff94bc080146815f31a18"
    }
  }
}

Response

{
  "errorId": 0,
  "taskId": 407533072
}

Create Task - With Proxy

Request

POST https://captcha69.com/createTask
Content-Type: application/json

{
  "clientKey": "max1_YOUR_API_KEY",
  "task": {
    "type": "CustomTask",
    "class": "altcha",
    "websiteURL": "https://example.com",
    "websiteKey": "",
    "userAgent": "userAgentPlaceholder",
    "metadata": {
      "challenge": "3dd28253be6cc0c54d95f7f98c517e68744597cc6e66109619d1ac975c39181c",
      "iterations": "5000",
      "salt": "46d5b1c8871e5152d902ee3f?edk=1493462145de1ce33a52fb569b27a364&codeChallenge=464Cjs7PbiJJhJZ_ReJ-y9UGGDndcpsnP6vS8x1nEJyTkhjQkJyL2jcnYEuMKcrG&expires=1761048664",
      "signature": "4b1cf0e0be0f4e5247e50b0f9a449830f1fbca44c32ff94bc080146815f31a18"
    },
    "proxyType": "http",
    "proxyAddress": "8.8.8.8",
    "proxyPort": 8080,
    "proxyLogin": "proxyLoginHere",
    "proxyPassword": "proxyPasswordHere"
  }
}

Response

{
  "errorId": 0,
  "taskId": 407533072
}

Get Task Result

Use the getTaskResult method to obtain the Altcha solution.

Request

POST https://captcha69.com/getTaskResult
Content-Type: application/json

{
  "clientKey": "max1_YOUR_API_KEY",
  "taskId": 407533072
}

Response

{
  "errorId": 0,
  "status": "ready",
  "solution": {
    "data": {
      "token": "eyJhbGdvcml...Ljc2MDEzM30==",
      "number": 44619
    }
  }
}

Solution Properties

PropertyTypeDescription
data.token String Base64-encoded solution containing all captcha parameters (algorithm, challenge, number, salt, signature).
data.number Integer The numeric solution for the Proof-of-Work challenge.

How to Find Required Parameters

Below are examples of extracting Altcha parameters needed to submit a solving task. Note that captcha implementations may differ across websites, so parameter extraction methods may vary.

  1. Open the Altcha page in your browser, launch DevTools (F12 or Ctrl+Shift+I), and go to the Network tab.
  2. Click on the captcha checkbox and complete it manually. In the Network search field, type any parameter name (e.g., "algorithm").
  3. Find the request that contains JSON with the parameters.
  4. Click on the request and, if necessary, go to the Response tab to view server-returned data.
  5. Copy the parameters — these values should be used to create the task.

In general, after activating the captcha on the page, you need to analyze network requests and identify all interactions related to its operation. For example, the screenshot below shows a request named altcha containing all key parameters:

After obtaining the required parameters, you need to pass them into the metadata object when creating a task. Example structure:

metadata: {
  challenge: "<challenge value>",
  iterations: "<maxnumber value>", // must be enclosed in quotes
  salt: "<salt value>",
  signature: "<signature value>",
}

Parameter Extraction Code

GET Request Example - Extract Parameters
const url = 'https://example-portal.mysite.rs.gov.br/Altcha/Example';

fetch(url, { method: 'GET' })
  .then(res => res.text())
  .then(data => console.log('Response:', data))
  .catch(err => console.error(err));
Parameter Interceptor - Browser Script
(function() {
  const keywords = ['algorithm','challenge','maxnumber','salt','signature'];
  const foundParams = {};

  const intercept = (url, body, text) => {
    keywords.forEach(key => {
      if ((url && url.includes(key)) || (body && body.includes(key)) || (text && text.includes(key))) {
        foundParams[key] = foundParams[key] || [];
        if (url?.includes(key)) foundParams[key].push(url);
        if (body?.includes(key)) foundParams[key].push(body);
        if (text?.includes(key)) foundParams[key].push(text);
      }
    });
    if (Object.keys(foundParams).length) console.log('Found parameters:', foundParams);
  };

  const originalFetch = window.fetch;
  window.fetch = async (...args) => {
    const [resource, config] = args;
    const url = typeof resource === 'string' ? resource : resource.url;
    const body = config?.body;
    const response = await originalFetch.apply(this, args);
    try {
      const text = await response.clone().text();
      intercept(url, body, text);
    } catch {}
    return response;
  };

  const originalOpen = XMLHttpRequest.prototype.open;
  const originalSend = XMLHttpRequest.prototype.send;

  XMLHttpRequest.prototype.open = function(method, url, ...rest) {
    this._url = url;
    return originalOpen.call(this, method, url, ...rest);
  };

  XMLHttpRequest.prototype.send = function(body) {
    this.addEventListener('load', () => intercept(this._url, body, this.responseText));
    return originalSend.call(this, body);
  };
})();

Automatic Altcha Solving with Playwright

In some cases, submitting just the number parameter is enough to confirm the solution. However, sometimes the site requires all parameters, encoded in base64.

The API returns number separately as well as the full set of parameters encoded in base64 (including number).

JavaScript (Node.js + Playwright) - Full Altcha Solving
const { chromium } = require("playwright");

const API_KEY = "max1_YOUR_API_KEY";
const ALTCHA_PAGE = "https://url_with_altcha";

(async () => {
  const browser = await chromium.launch({ headless: false, devtools: true });
  const context = await browser.newContext();
  const page = await context.newPage();

  await page.route("**/*", (route) => {
    const url = route.request().url();
    if (url.includes("captcha69.com")) return route.abort();
    return route.continue();
  });

  let challengeResp = null;
  page.on("response", async (response) => {
    try {
      if (response.url().includes("/Altcha/GerarDesafio")) {
        challengeResp = await response.json();
        console.log("Captured /Altcha/GerarDesafio:", challengeResp);
      }
    } catch {}
  });

  await page.goto(ALTCHA_PAGE, { waitUntil: "networkidle" });

  try {
    await page.waitForSelector("altcha-widget input[type='checkbox']", { timeout: 10000 });
    await page.click("altcha-widget input[type='checkbox']");
  } catch {
    const widgetHandle = await page.$("altcha-widget");
    if (widgetHandle) await widgetHandle.click();
  }

  const start = Date.now();
  while (!challengeResp && Date.now() - start < 30000) {
    await new Promise((r) => setTimeout(r, 300));
  }
  if (!challengeResp) {
    console.error("Failed to capture /Altcha/GerarDesafio.");
    await browser.close();
    return;
  }

  const { challenge, salt, signature, maxnumbers } = challengeResp;

  const createTaskBody = {
    clientKey: API_KEY,
    task: {
      type: "CustomTask",
      class: "altcha",
      websiteURL: ALTCHA_PAGE,
      websiteKey: "",
      userAgent: "userAgentPlaceholder",
      metadata: {
        challenge,
        iterations: maxnumbers,
        salt,
        signature,
      },
    },
  };

  const taskResp = await fetch("https://captcha69.com/createTask", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(createTaskBody),
  }).then((r) => r.json());

  console.log("CreateTask response:", taskResp);
  if (!taskResp || !taskResp.taskId) {
    console.error("CreateTask failed:", taskResp);
    await browser.close();
    return;
  }

  const taskId = taskResp.taskId;

  let fullSolution = null;
  const maxPollMs = 120000;
  const pollStart = Date.now();
  while (Date.now() - pollStart < maxPollMs) {
    const res = await fetch("https://captcha69.com/getTaskResult", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ clientKey: API_KEY, taskId }),
    }).then((r) => r.json());

    if (res.status === "ready") {
      fullSolution = res.solution;
      console.log("Full solution:", fullSolution);
      break;
    }
    await new Promise((r) => setTimeout(r, 3000));
  }

  if (!fullSolution) {
    console.error("Solution was not received within the allocated time.");
    await browser.close();
    return;
  }

  const token =
    (fullSolution && fullSolution.data && fullSolution.data.token) ||
    fullSolution.token ||
    (fullSolution && fullSolution.data) ||
    null;

  if (!token) {
    console.error("Token not found:", fullSolution);
    await browser.close();
    return;
  }

  console.log("Token:", token);
  await browser.close();
})();