Captcha-solver in C# met HttpClient: .NET-voorbeeld (2026)
In C# is een captcha-solver een kleine klasse rond HttpClient. Je stuurt de sitekey en de paginaURL naar de Scarnox-API, leest het token uit de JSON-respons, en dient het in bij het formulier van de site. Deze gids bouwt die klasse voor .NET 8, voor PopularCaptcha, dat Scarnox vandaag zonder proxy oplost.
Begin met gratis proefcredit, zonder creditcard en probeer de code tegen een pagina die je beheert voordat je hem ergens anders gebruikt.
Vereisten
- .NET 8 SDK (
dotnet --version). - Een Scarnox-API-sleutel, gelezen uit een omgevingsvariabele.
- De sitekey van de PopularCaptcha-widget van de pagina. Voor hulp bij het vinden ervan, zie hoe je de captcha-sitekey vindt.
Het project aanmaken
dotnet new console -n CaptchaDemo
cd CaptchaDemo
Er zijn geen extra pakketten nodig. System.Net.Http en System.Text.Json maken deel uit van het framework.
De solverklasse
De klasse hieronder bezit één HttpClient met de Bearer-header en een time-out van 185 seconden. Ze geeft het token terug, of gooit een uitzondering met de foutmelding van de API:
// ScarnoxSolver.cs
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
public sealed class ScarnoxSolver : IDisposable
{
private const string ApiUrl = "https://api.scarnox.com/api/tasks/create";
private readonly HttpClient _http;
public ScarnoxSolver(string apiKey)
{
_http = new HttpClient { Timeout = TimeSpan.FromSeconds(185) };
_http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
}
public async Task<string> SolveAsync(
string sitekey,
string pageUrl,
bool invisible = false,
CancellationToken ct = default)
{
var body = new Dictionary<string, object>
{
["captcha_type"] = "PopularCaptchaTaskProxyless",
["site_key"] = sitekey,
["site_url"] = pageUrl,
};
if (invisible)
{
body["is_invisible"] = true;
}
// De aanroep keert terug wanneer het token klaar is. Er wordt niet gepolld.
using var resp = await _http.PostAsJsonAsync(ApiUrl, body, ct);
var data = await resp.Content.ReadFromJsonAsync<CreateTaskResponse>(cancellationToken: ct)
?? throw new InvalidOperationException(
$"HTTP {(int)resp.StatusCode}: empty response");
if (data.ErrorId != 0)
{
throw new InvalidOperationException($"{data.ErrorCode}: {data.ErrorDescription}");
}
return data.Solution?.Token
?? throw new InvalidOperationException("Response had no token");
}
public void Dispose() => _http.Dispose();
}
public sealed class CreateTaskResponse
{
[JsonPropertyName("errorId")]
public int ErrorId { get; set; }
[JsonPropertyName("errorCode")]
public string? ErrorCode { get; set; }
[JsonPropertyName("errorDescription")]
public string? ErrorDescription { get; set; }
[JsonPropertyName("solution")]
public Solution? Solution { get; set; }
}
public sealed class Solution
{
[JsonPropertyName("token")]
public string? Token { get; set; }
}
De errorId-controle is de belangrijkste regel. De API geeft 0 bij succes. Elke andere waarde komt met errorCode en errorDescription, en de klasse toont beide.
Het token indienen
Het token gaat naar het formulier van de site. Gebruik een tweede HttpClient met een cookiecontainer, zodat de sessie die het formulier heeft geladen wordt hergebruikt bij de POST:
// Program.cs
using System.Net;
var apiKey = Environment.GetEnvironmentVariable("SCARNOX_API_KEY")
?? throw new InvalidOperationException("Set SCARNOX_API_KEY");
const string pageUrl = "https://example.com/signup";
const string sitekey = "YOUR-SITEKEY-UUID";
using var solver = new ScarnoxSolver(apiKey);
string token = "";
// Probeer tijdelijke fouten opnieuw. Mislukte oplossingen worden niet in rekening gebracht.
for (int attempt = 1; attempt <= 3; attempt++)
{
try
{
token = await solver.SolveAsync(sitekey, pageUrl);
break;
}
catch (InvalidOperationException ex) when (attempt < 3)
{
Console.Error.WriteLine($"Attempt {attempt} failed: {ex.Message}");
await Task.Delay(TimeSpan.FromSeconds(attempt));
}
}
var cookies = new CookieContainer();
var handler = new HttpClientHandler { CookieContainer = cookies, UseCookies = true };
using var site = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(60) };
// Eerst een GET, zodat de site zijn sessiecookie instelt.
await site.GetAsync(pageUrl);
using var form = new FormUrlEncodedContent(new Dictionary<string, string>
{
["email"] = "you@example.com",
["h-captcha-response"] = token,
["g-recaptcha-response"] = token,
});
using var response = await site.PostAsync(pageUrl, form);
Console.WriteLine($"Status: {(int)response.StatusCode}");
Uitvoeren:
set SCARNOX_API_KEY=scarnox_YOURAPIKEY
dotnet run
In PowerShell gebruik je in plaats daarvan $env:SCARNOX_API_KEY = "scarnox_YOURAPIKEY".
Waarom het zo is opgezet
**Één HttpClient per solver.** HttpClient is bedoeld om hergebruikt te worden, niet om bij elke aanroep opnieuw aan te maken. De solver bezit er één en ruimt hem aan het eind op.
Een time-out van 185 seconden. De API blokkeert totdat het token klaar is. Een kortere time-out annuleert oplossingen die bijna klaar waren.
Getypte deserialisatie. ReadFromJsonAsync zet de JSON om naar CreateTaskResponse, zodat de fout- en tokencontroles lezen als normale C#.
Het verzenden van het formulier. De site ontvangt zowel h-captcha-response als g-recaptcha-response, omdat sites de ene of de andere lezen. De cookiecontainer houdt de sessie vast tussen de GET en de POST.
Timing
Het token verloopt na ongeveer twee minuten. Los op vlak voordat je verzendt. Als je vroeg in een batch oplost en veel later verzendt, is het token verouderd. Verlopen captchatokens behandelt de details.
Onzichtbare widgets
Geef invisible: true mee aan SolveAsync wanneer de widget onzichtbaar is. Het verzoek bevat dan is_invisible: true. Sommige pagina's hebben een JavaScript-callback nodig die een server-side client niet kan activeren. In dat geval is een browserautomatiseringstool de betere keuze. De gids over onzichtbare captcha behandelt de patronen.
Verantwoord scrapen
Als het programma publieke pagina's scrapet, controleer dan eerst robots.txt en de voorwaarden van de site. Gebruik een vertraging tussen verzoeken, en houd alleen de persoonsgegevens die je nodig hebt. Voor de juridische achtergrond, zie is webscraping legaal.
Prijzen
Scarnox rekent per geslaagde oplossing, en mislukte oplossingen zijn gratis. Zie actuele prijzen voor de tarieven. Begin met gratis proefcredit, zonder creditcard.