In dit artikel hebben we geprobeerd antwoord te geven op alle belangrijke vragen. De eerste stap bij het oplossen van het vraagstuk is vaststellen welk beveiligingssysteem wordt gebruikt. Daarvoor kun je de lijst met populaire captcha’s en anti-botbeveiligingssystemen raadplegen, met visuele voorbeelden en kernkenmerken die je helpen snel te bepalen waarmee je te maken hebt.
Als je ontdekt dat je website ALTCHA gebruikt, is de volgende stap om de eigenschappen en werking ervan uitgebreider te bestuderen. In dit artikel vind je ook een handleiding voor het integreren van ALTCHA, zodat je volledig begrijpt hoe het systeem op je website werkt. Zo kun je niet alleen de huidige bescherming beter doorgronden, maar ook het onderhoud ervan goed plannen.
Bij het testen van formulieren met ALTCHA moet je vaak bevestigen dat de captcha goed is ingebouwd en werkt.
Je kunt de captcha op je site handmatig testen.
Voor automatische oplossingen kun je tools zoals CapMonster Cloud gebruiken. Deze ontvangen de captcha-parameters, verwerken ze op hun servers en sturen een token terug dat je in het formulier kunt zetten om de controle zonder gebruikersinteractie te omzeilen.
Werken met CapMonster Cloud via de API bestaat doorgaans uit de volgende stappen:
Het verzoek om ALTCHA op te lossen moet de volgende parameters bevatten:
type - CustomTask
class - altcha
websiteURL - adres van de pagina waar de captcha wordt opgelost
websiteKey - voor deze taak is het toegestaan een lege string te sturen.
challenge (in metadata) - unieke taak-ID verkregen van de webpagina.
iterations (in metadata) - aantal iteraties of maximaal aantal voor berekeningen. Belangrijk: de parameter iterations komt overeen met de waarde maxnumber!
salt (in metadata) - salt verkregen van de site, gebruikt voor het genereren van hashes.
signature (in metadata) - digitale handtekening van het verzoek.
userAgent - User-Agent van de browser. Stuur alleen actuele UA van Windows.
https://api.capmonster.cloud/createTask{
"clientKey": "API_KEY",
"task": {
"type": "CustomTask",
"class": "altcha",
"websiteURL": "https://example.com",
"websiteKey": "",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
"metadata": {
"challenge": "3dd28253be6cc0c54d95f7f98c517e68744597cc6e66109619d1ac975c39181c",
"iterations": "5000",
"salt":"46d5b1c8871e5152d902ee3f?edk=1493462145de1ce33a52fb569b27a364&codeChallenge=464Cjs7PbiJJhJZ_ReJ-y9UGGDndcpsnP6vS8x1nEJyTkhjQkJyL2jcnYEuMKcrG&expires=1761048664",
"signature": "4b1cf0e0be0f4e5247e50b0f9a449830f1fbca44c32ff94bc080146815f31a18"
}
}
}
{
"errorId":0,
"taskId":407533072
}https://api.capmonster.cloud/getTaskResult{
"clientKey":"API_KEY",
"taskId": 407533072
}
{
"errorId": 0,
"status": "ready",
"solution": {
"data": {
"token": "eyJhbGdvcml0aG0iOiJTSEEtMjU2IiwiY2hhbGxlbmdlIjoiNjMxOGUzYzc2NjhlOTZiMmFlYjg2NGU2NmRmMTliODRkYmYwZDBhMWRjNjYwMDdiMGM5ZGI4ODZiNTUxNjQxNiIsIm51bWJlciI6MTY0NDcsInNhbHQiOiJiMTQ1YWE5ZmU5MjA3NjBiMDgxYTAwNTMiLCJzaWduYXR1cmUiOiI5NzM4MmJlODE2NDUwNzk5MzlhYmU2M2ZkYzZjN2E3ZGYwOTM5MzNjODljZTk0ZjgzNTgxYmUyNDU3ZmI4MDM0IiwidG9vayI6MTczLjl9",
"number": "16447"
}
}
}
// npm install playwright
// npx playwright install chromium
const { chromium } = require("playwright");
const API_KEY = "YOUR_API_KEY";
const ALTCHA_PAGE = "https://example.com"; // Jouw site met ALTCHA
(async () => {
const browser = await chromium.launch({ headless: false, devtools: true });
const context = await browser.newContext();
const page = await context.newPage();
// Alle antwoorden van het Altcha-endpoint opvangen
let challengeResp = null;
page.on("response", async (response) => {
try {
const url = response.url();
if (url.startsWith("https://captcha.example.com/altcha")) { // Altcha-endpoint
challengeResp = await response.json();
console.log("Captured Altcha response:", challengeResp);
}
} catch (err) {
console.warn("Error parsing Altcha response:", err);
}
});
await page.goto(ALTCHA_PAGE, { waitUntil: "networkidle" });
// Klik op het widget, indien aanwezig
const widgetHandle = await page.$("altcha-widget");
if (widgetHandle) {
try {
await widgetHandle.click();
} catch {}
}
// Wacht op het verschijnen van de challenge
const start = Date.now();
while (!challengeResp && Date.now() - start < 60000) { // Timeout verhoogd
await new Promise((r) => setTimeout(r, 300));
}
if (!challengeResp) {
console.error("Failed to capture Altcha challenge.");
await browser.close();
return;
}
const { challenge, salt, signature, maxnumbers } = challengeResp;
// Taak aanmaken op CapMonster Cloud
const createTaskBody = {
clientKey: API_KEY,
task: {
type: "CustomTask",
class: "altcha",
websiteURL: ALTCHA_PAGE,
websiteKey: "",
userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
metadata: {
challenge,
iterations: maxnumbers || 100000,
salt,
signature,
},
},
};
const taskResp = await fetch("https://api.capmonster.cloud/createTask", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(createTaskBody),
}).then((r) => r.json());
console.log("CreateTask response:", taskResp);
if (!taskResp?.taskId) {
console.error("CreateTask failed:", taskResp);
await browser.close();
return;
}
const taskId = taskResp.taskId;
// Oplossing ophalen
let fullSolution = null;
const pollStart = Date.now();
while (Date.now() - pollStart < 120000) {
const res = await fetch("https://api.capmonster.cloud/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("Solution:", fullSolution);
break;
}
await new Promise((r) => setTimeout(r, 3000));
}
if (!fullSolution) {
console.error("No solution received in time.");
await browser.close();
return;
}
const token = fullSolution?.data?.token || fullSolution?.token || fullSolution?.data;
if (!token) {
console.error("Token not found in solution:", fullSolution);
await browser.close();
return;
}
//Token invoegen
await page.evaluate((t) => {
let input = document.querySelector("#captchaParaValidar");
if (!input) {
input = document.createElement("input");
input.type = "hidden";
input.id = "captchaParaValidar";
input.name = "captchaParaValidar";
(document.querySelector("form") || document.body).appendChild(input);
}
input.value = t;
let alt = document.querySelector('input[name="altcha"]');
if (!alt) {
alt = document.createElement("input");
alt.type = "hidden";
alt.name = "altcha";
(document.querySelector("form") || document.body).appendChild(alt);
}
alt.value = t;
const widget = document.querySelector("altcha-widget");
if (widget) {
widget.setAttribute("data-state", "verified");
const checkbox = widget.querySelector("input[type='checkbox']");
if (checkbox) {
checkbox.checked = true;
checkbox.dispatchEvent(new Event("change", { bubbles: true }));
}
const label = widget.querySelector(".altcha-label");
if (label) label.textContent = "Verified";
}
}, token);
console.log("Token injected:", token);
})();1. Widget installeren
Optie 1 — via CDN (het eenvoudigst). Voeg toe aan de <head> van je HTML:
<script async defer src="https://cdn.jsdelivr.net/gh/altcha-org/altcha/dist/altcha.min.js" type="module"></script>Optie 2 — via npm:
npm install altchaImporteer het widget in je JS-bestand:
import "altcha";2. Widget toevoegen aan formulier.
Plaats de <altcha-widget> component in het formulier waar bescherming nodig is:
<form method="POST" action="/submit">
<altcha-widget challengeurl="/altcha/challenge"></altcha-widget>
<button type="submit">Send</button>
</form>challengeurl — jouw serverendpoint om challenge uit te geven.
Als je ALTCHA Sentinel gebruikt (kant-en-klare serverbescherming tegen bots en spam met machine learning en verkeeranalyse), gebruik dan de URL hiervan in plaats van je eigen server:
<altcha-widget
challengeurl="https://sentinel.example.com/v1/challenge?apiKey=YOUR_API_KEY">
</altcha-widget>3. Server-side verificatie.
Hoe verificatie verloopt:
Verificatie via ALTCHA Sentinel:
import { verifyServerSignature } from 'altcha-lib';
// Geheime API-sleutel gegenereerd in Sentinel
const apiKeySecret = 'sec_...';
// Payload van het widget
const payload = '...';
// Verificatie
const { verificationData, verified } = await verifyServerSignature(payload, apiKeySecret);
if (verified) {
// Verificatie geslaagd — formuliergegevens kunnen worden verwerkt
}
const resp = await fetch('https://sentinel.example.com/v1/verify/signature', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payload }),
});
const { verified } = await resp.json();
if (verified) {
// Verificatie geslaagd — formulier verwerken
}
API voorkomt automatisch hergebruik van dezelfde payload.
4. Verificatie zonder Sentinel (eigen server)
Genereren van challenge:
import { createChallenge } from 'altcha-lib';
const hmacKey = '$ecret.key'; // Jouw HMAC geheime sleutel
const challenge = await createChallenge({ hmacKey });
// Challenge in JSON teruggeven voor widgetPayload-verificatie bij formulierverzending:
import { verifySolution } from 'altcha-lib';
const hmacKey = '$ecret.key'; // Jouw HMAC geheime sleutel
const verified = await verifySolution(payload, hmacKey);
if (verified) {
// Verificatie geslaagd — formuliergegevens verwerken
}
In dit geval maak je zelf de /altcha/challenge endpoint om challenges uit te geven en deze op de server te verifiëren.
Als je een website in beheer krijgt waarop al een captcha of een ander beveiligingssysteem is geïnstalleerd en je geen toegang hebt tot de code, is dat geen probleem! Het is vrij eenvoudig te bepalen welke technologie precies wordt gebruikt. Voor het controleren of alles correct werkt, kun je de herkenningsservice CapMonster Cloud in een geïsoleerde testomgeving gebruiken, zodat je zeker weet dat het tokenverwerkingsmechanisme en de validatielogica correct functioneren.
In het geval van ALTCHA is het voldoende om het systeem te herkennen, het gedrag te analyseren en te bevestigen dat de beveiliging correct werkt. In het artikel hebben we laten zien hoe je ALTCHA kunt herkennen en waar je instructies vindt om het te koppelen of opnieuw te configureren, zodat je de bescherming met vertrouwen kunt onderhouden en de werking onder controle kunt houden.