CAPTCHA Solving 11 min read

Web Scraper CAPTCHA Solving with DeathByCaptcha in C#

Handle web scraper CAPTCHA challenges: build a C# solver on the DeathByCaptcha API, from image upload to token submission. Follow the coding guide.

ST
Scraping.Pro Team
Data collection for business needs
Published: 3 August 2025

Sooner or later every scraper meets a web scraper CAPTCHA — that "prove you're human" wall a site throws up when it decides your traffic looks automated. A single CAPTCHA stops a script cold, and a site that challenges every request can shut a crawler down entirely. This guide shows how to get past them programmatically in C# using a CAPTCHA-solving service, with DeathByCaptcha as the worked example, covering both classic image challenges and modern token-based ones like reCAPTCHA v2/v3.

Before the code, one thing worth saying up front: the best way to handle a web scraping CAPTCHA is to not trigger it. Solving services are the fallback for when you can't avoid the challenge — we'll cover the avoidance side too, because it's usually cheaper and faster than solving.

Contents

  1. What CAPTCHAs you actually face in 2026
  2. How CAPTCHA solving services work
  3. Solving an image CAPTCHA in C#
  4. Solving reCAPTCHA v2 (token-based)
  5. reCAPTCHA v3, hCaptcha and Turnstile
  6. DeathByCaptcha across languages and challenge types
  7. Don't solve what you can avoid
  8. Alternatives to DeathByCaptcha
  9. FAQ

1. What CAPTCHAs you actually face in 2026

The CAPTCHA landscape has shifted a lot since distorted-text images were the norm. Today a scraper mostly runs into:

  • Distorted-text / image CAPTCHAs — still common on older sites, logins, and government portals. You get an image, you return the characters.
  • reCAPTCHA v2 ("I'm not a robot" checkbox, sometimes followed by an image grid). Server-side you validate a token, not text.
  • reCAPTCHA v3 — invisible; it scores every request from 0.0 (bot) to 1.0 (human) and never shows a challenge. You still need a valid token with a passing score.
  • hCaptcha — a privacy-focused reCAPTCHA competitor with the same token model.
  • Cloudflare Turnstile — a lightweight, mostly invisible challenge that also resolves to a token.

The old approach — screenshotting the page, cropping out the CAPTCHA image, and sending the pixels off for recognition — still applies to the first category. Everything after that is token-based: the service doesn't read an image, it produces a solution token that you inject back into the page or POST to the form endpoint. Getting this distinction right is most of the battle.

2. How CAPTCHA solving services work

A CAPTCHA solving service is an API you send a challenge to and get back a solution. Under the hood they combine trained ML models with human workers for the cases machines still fail. The workflow is always the same three steps:

  1. Submit the challenge — image bytes, or (for token CAPTCHAs) the site key plus the page URL.
  2. Poll the service until it returns a result. Image CAPTCHAs come back in seconds; reCAPTCHA can take 10–60 seconds.
  3. Use the result — type the text into the form, or inject the token and submit.

DeathByCaptcha (DBC) is one of the oldest services in this market and supports all the challenge types above through a single API with client libraries in C#, Python, Java, PHP, Node.js and others. The examples below use its HTTP API, which is stable and language-agnostic, plus its C# client where that's simpler.

3. Solving an image CAPTCHA in C

For a classic image CAPTCHA you need the image bytes. If the image is a normal <img src="...">, just download it with HttpClient (reusing your scraper's cookies so you get the same challenge the page rendered). If it's drawn dynamically or you're already driving a browser, grab the element's screenshot — modern Selenium exposes per-element screenshots, so the old "screenshot the whole page and crop by coordinates" dance is no longer necessary:

c#
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

using var driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://example.com/protected");

// Screenshot just the CAPTCHA element — no cropping math required.
var captchaEl = driver.FindElement(By.Id("captcha"));
byte[] imageBytes = ((ITakesScreenshot)captchaEl).GetScreenshot().AsByteArray;

Now hand those bytes to DeathByCaptcha. Using the official C# client:

c#
using DeathByCaptcha;

var client = new SocketClient("your_username", "your_password");

// Optional: check your balance before spending it.
Console.WriteLine($"Balance: {client.GetBalance()}");

Captcha result = client.Decode(imageBytes, 60);   // 60s timeout
if (result != null && result.Solved && result.Correct)
{
    Console.WriteLine($"Solved: {result.Text}");

    driver.FindElement(By.Name("captcha_code")).SendKeys(result.Text);
    driver.FindElement(By.Name("submit")).Click();

    // If the site rejects it, report the bad solve so you aren't charged.
    bool accepted = driver.PageSource.Contains("SUCCESS");
    if (!accepted)
        client.Report(result);
}
else
{
    Console.WriteLine("CAPTCHA could not be solved.");
}

Two habits worth keeping from the original pattern: check the result before using it (Solved && Correct), and report incorrect solves with client.Report(...). Reputable services refund reported misreads, so reporting keeps your costs honest and improves their models.

4. Solving reCAPTCHA v2 (token-based)

Here's the shift that trips people up. With reCAPTCHA you never send an image. You send the site key (a public value baked into the page) and the page URL, the service does the interaction on its side, and it returns a g-recaptcha-response token. You then inject that token into the page and submit — or POST it straight to the form's backend.

First, find the site key. It's in the page HTML, usually as data-sitekey on the reCAPTCHA <div>:

c#
var siteKey = driver.FindElement(By.CssSelector(".g-recaptcha"))
                    .GetAttribute("data-sitekey");
var pageUrl = driver.Url;

Then submit the job to DeathByCaptcha's HTTP API and poll for the token. Doing it over raw HTTP makes the flow explicit and works identically in any language:

c#
using System.Net.Http;
using System.Text.Json;

static async Task<string> SolveRecaptchaV2(string user, string pass,
                                           string siteKey, string pageUrl)
{
    using var http = new HttpClient { BaseAddress = new Uri("https://api.dbcapi.me/") };

    var tokenParams = JsonSerializer.Serialize(new
    {
        googlekey = siteKey,
        pageurl   = pageUrl
    });

    // 1. Submit the job (type 4 = reCAPTCHA token).
    var submit = new FormUrlEncodedContent(new Dictionary<string, string>
    {
        ["username"]     = user,
        ["password"]     = pass,
        ["type"]         = "4",
        ["token_params"] = tokenParams
    });
    http.DefaultRequestHeaders.Add("Accept", "application/json");
    var created = await http.PostAsync("api/captcha", submit);
    var doc = JsonDocument.Parse(await created.Content.ReadAsStringAsync());
    int id = doc.RootElement.GetProperty("captcha").GetInt32();

    // 2. Poll until the token is ready.
    for (int i = 0; i < 30; i++)
    {
        await Task.Delay(5000);
        var poll = await http.GetAsync($"api/captcha/{id}");
        var pd = JsonDocument.Parse(await poll.Content.ReadAsStringAsync()).RootElement;
        var text = pd.GetProperty("text").GetString();
        if (!string.IsNullOrEmpty(text))
            return text;   // the g-recaptcha-response token
    }
    throw new TimeoutException("reCAPTCHA not solved in time.");
}

Finally, put the token where reCAPTCHA expects it and submit. The response goes into a hidden #g-recaptcha-response textarea; set it with JavaScript, then submit the form:

c#
var token = await SolveRecaptchaV2(user, pass, siteKey, pageUrl);

((IJavaScriptExecutor)driver).ExecuteScript(
    "document.getElementById('g-recaptcha-response').innerHTML = arguments[0];",
    token);

driver.FindElement(By.Id("submit")).Click();

If you're not driving a browser at all — just talking to the form's HTTP endpoint — you can skip Selenium entirely and POST the token as the g-recaptcha-response field alongside the form's other values. That's faster and lighter, and it's how most production scrapers do it.

5. reCAPTCHA v3, hCaptcha and Turnstile

reCAPTCHA v3 is the same token flow with two extra parameters: an action (the page's declared action name, e.g. login) and a target minimum score. You pass those alongside the site key, and the service returns a token that should clear the site's threshold. Because v3 is score-based and invisible, high-quality residential proxies matter even more here — a token minted from a flagged IP scores poorly no matter who solved it.

hCaptcha and Cloudflare Turnstile work exactly like reCAPTCHA v2 from your side: find the site key, submit site key + page URL, receive a token, inject it into the page's hidden response field (h-captcha-response or the Turnstile input) and submit. Only the challenge type identifier and the field name change; your integration code barely moves.

6. DeathByCaptcha across languages and challenge types

DeathByCaptcha has kept its clients current as the challenge types evolved — it added token-based reCAPTCHA v2 solving, then reCAPTCHA v3 scoring support, and maintains ready-made examples beyond C#. If your stack isn't .NET, the same account and API cover:

  • Node.js — the client and reCAPTCHA examples make it a natural fit for Playwright/Puppeteer-based scrapers.
  • Python — pairs well with requests, Selenium and Scrapy.
  • PHP, Java, Go, Ruby — official or community clients exist for each.
  • Browser-automation tools — examples exist for macro/RPA setups too, so you're not locked into a single language.

Whatever the language, the three-step submit → poll → use loop is identical; only the SDK syntax changes. Pick the client that matches your scraper rather than rewriting the scraper around the CAPTCHA service.

7. Don't solve what you can avoid

Every solved CAPTCHA costs money and adds 5–60 seconds of latency. Before you wire up a solver, cut the number of challenges you trigger in the first place — this is the single biggest lever on both cost and speed:

  • Rotate good proxies. Most CAPTCHAs fire because too many requests came from one IP. A pool of rotating residential proxies keeps each request looking like a different ordinary user.
  • Slow down and randomize. Human-like pacing and jittered delays trip far fewer defenses than a tight loop.
  • Use a real browser fingerprint. Headless-browser detection is a common trigger; a properly configured headless browser with a genuine user agent and normal viewport avoids many challenges outright.
  • Keep sessions and cookies. Once a site trusts a session, it challenges it less. Reuse cookies instead of starting cold every request.

CAPTCHAs are one layer of a broader anti-scraping stack; treat solving as the last resort, after avoidance has done its job.

8. Alternatives to DeathByCaptcha

DeathByCaptcha isn't the only option, and it's worth knowing the field. The main services all expose the same submit/poll/token API, so switching is mostly a config change:

Service Notes
DeathByCaptcha One of the oldest; image + reCAPTCHA v2/v3 + hCaptcha; multi-language clients
2Captcha Very broad challenge coverage, large workforce, well-documented API
Anti-Captcha Similar coverage; strong token-CAPTCHA support
CapMonster Cloud ML-heavy, often cheaper for high volume on supported types
CapSolver / others Newer AI-first services targeting reCAPTCHA/hCaptcha/Turnstile

For classic image CAPTCHAs at low volume you can also run a local OCR/ML model instead of paying per solve — worthwhile only when the images are simple and the volume is high enough to justify the setup.

FAQ

Is bypassing a CAPTCHA while scraping legal? Using a solving service isn't inherently illegal, but it may breach a site's terms of service, and scraping the data behind it carries its own legal considerations. Scrape public data, respect robots.txt and rate limits, and get advice for anything sensitive.

Why did my reCAPTCHA token get rejected even though it solved? Usually the IP. reCAPTCHA (especially v3) scores the token against the requesting IP and fingerprint. Solve from the same proxy/session that will submit the form, and use clean residential IPs.

How much does solving cost? Services price per thousand solves, with token CAPTCHAs costing more than image ones. Pricing changes, so check the provider — but the real cost driver is how many CAPTCHAs you trigger, which is why avoidance pays off.

Do I need Selenium? No. If you can POST the token to the form endpoint directly, a plain HTTP client is faster and cheaper than a full browser. Use a browser only when the page genuinely requires JavaScript execution to submit.


Fighting CAPTCHAs, proxies and anti-bot systems on every run gets old fast. If you'd rather receive clean, structured data than maintain the plumbing, scraping.pro runs the whole pipeline — CAPTCHA handling included — as a done-for-you web scraping service.