The DeathByCaptcha C++ client is the official library for the DeathByCaptcha captcha solving service, built for developers and teams that need reliable automation in production. It provides a clean, well-documented C++20 interface for integrating CAPTCHA solving into bots, data extraction jobs, and browser workflows, including use cases where a captcha solver for web scraping is required to keep pipelines stable when target sites enforce CAPTCHA challenges. It supports both the HTTPS API (encrypted transport β recommended when security is a priority) and the socket-based API (faster and lower latency, recommended for high-throughput production workloads).
Key features:
- π§© Send image, audio and modern token-based CAPTCHA types (reCAPTCHA v2/v3, Turnstile, GeeTest, etc.).
- π Unified client API across HTTP and socket transports β switching between them requires changing a single line.
- π Thread-safe by design; each client instance manages its own connection/handle internally.
- ποΈ Multiplatform: Linux, Windows, macOS. Requires C++20 (GCC 12+, Clang 14+, MSVC 2022+) and CMake 3.21+.
Quick start example (HTTP):
#include "deathbycaptcha/deathbycaptcha.hpp"
#include <iostream>
int main() {
dbc::HttpClient client("your_username", "your_password");
auto result = client.decode("path/to/captcha.jpg", 120);
if (result) {
std::cout << result->text.value_or("") << '\n';
}
}π Transport options: Use
dbc::HttpClientfor encrypted HTTPS communication β credentials and data travel over TLS. Usedbc::SocketClientfor lower latency and higher throughput β it is faster but communicates over a plain TCP connection toapi.dbcapi.meon ports8123β8130.
- Installation
- How to Use DBC API Clients
- Credentials & Configuration
- CAPTCHA Types Quick Reference & Examples
- CAPTCHA Types Extended Reference
| Dependency | Minimum version | Notes |
|---|---|---|
| CMake | 3.21 | Required |
| Ninja | any | Recommended generator |
| libcurl | 7.x | System package |
| nlohmann/json | 3.11 | Auto-fetched via FetchContent if not found |
| GTest / GMock | 1.14 | Auto-fetched for tests |
sudo apt-get install cmake ninja-build libcurl4-openssl-dev nlohmann-json3-devbrew install cmake ninja curl nlohmann-jsonvcpkg install curl nlohmann-jsongit clone https://github.com/deathbycaptcha/deathbycaptcha-api-client-cpp.git
cd deathbycaptcha-api-client-cpp
# Configure & build (Debug, shared+static libs + unit tests)
cmake --preset default
cmake --build --preset default
# Run unit tests
ctest --preset default --output-on-failureOther presets available: release, coverage, integration, examples.
To link the library in your own project:
find_package(DeathByCaptchaCpp REQUIRED)
target_link_libraries(my_app PRIVATE DeathByCaptcha::cpp)All clients must be instantiated with your DeathByCaptcha credentials β either username and password, or an authtoken (available in the DBC user panel). Replace HttpClient with SocketClient to use the socket transport instead.
#include "deathbycaptcha/deathbycaptcha.hpp"
// Username + password (HTTPS transport β encrypted, recommended when security matters)
dbc::HttpClient client(username, password);
// Username + password (socket transport β faster, lower latency, recommended for high throughput)
// dbc::SocketClient client(username, password);
// Authtoken only
// dbc::HttpClient client("your_authtoken");| Transport | Class | Best for |
|---|---|---|
| HTTPS | dbc::HttpClient |
Encrypted TLS transport β safer for credential handling and network-sensitive environments |
| Socket | dbc::SocketClient |
Plain TCP β faster and lower latency, recommended for high-throughput production workloads |
Both clients share the same interface. Below is a summary of every available method.
Recommended pattern for parallel solving: one client instance per thread.
- Do not share a single client instance between workers if your goal is maximum throughput.
- Create one
dbc::HttpClientordbc::SocketClientper worker thread. - Each worker can independently call
decode(),upload(), andget_captcha().
Ready-to-run samples:
- HTTP (one instance per thread):
examples/example.ThreadSafe_Http.cpp - Socket (one instance per thread):
examples/example.ThreadSafe_Socket.cpp
Build and run:
cmake --preset examples
cmake --build --preset examples
# Basic mode (no DBC_IMAGE_PATH): each thread does get_balance()
export DBC_USERNAME="your_username"
export DBC_PASSWORD="your_password"
export DBC_THREADS=2
./build/examples/examples/ex_threadsafe_http
./build/examples/examples/ex_threadsafe_socketIf DBC_IMAGE_PATH is set, workers use decode() with that image path.
| Method | Signature | Returns | Description |
|---|---|---|---|
upload() |
upload(path, params) |
Captcha |
Upload a CAPTCHA for solving without waiting. Pass a file path for image/audio; use params for token types. |
upload() |
upload(span<uint8_t>, params) |
Captcha |
Upload raw bytes without waiting. |
decode() |
decode(file, timeout, params) |
optional<Captcha> |
Upload and poll until solved or timed out. Preferred method for most integrations. |
get_captcha() |
get_captcha(long long cid) |
Captcha |
Fetch status and result of a previously uploaded CAPTCHA by its numeric ID. |
get_text() |
get_text(long long cid) |
optional<string> |
Convenience wrapper β returns only the solved text. |
report() |
report(long long cid) |
bool |
Report a CAPTCHA as incorrectly solved to request a refund. Only report genuine errors. |
get_balance() |
get_balance() |
double |
Return the current account balance in US cents. |
get_user() |
get_user() |
User |
Return full account details. |
close() |
close() |
void |
Release the underlying connection/socket (called automatically on destruction). |
decode() and upload() return a dbc::Captcha struct:
struct Captcha {
long long captcha; // Numeric CAPTCHA ID assigned by DBC
std::optional<std::string> text; // Solved text or token (nullopt if still pending)
bool is_correct; // Whether DBC considers the solution correct
};// Example result
result->captcha // 123456789
result->text // "03AOPBWq_..." (or std::nullopt if pending)
result->is_correct // true#include "deathbycaptcha/deathbycaptcha.hpp"
#include <iostream>
int main() {
dbc::HttpClient client("your_username", "your_password");
try {
std::cout << "Balance: " << client.get_balance() << " US cents\n";
auto result = client.decode("path/to/captcha.jpg", 120);
if (result) {
std::cout << "Solved CAPTCHA " << result->captcha
<< ": " << result->text.value_or("") << '\n';
// Report only if you are certain the solution is wrong:
// client.report(result->captcha);
} else {
std::cout << "Timed out\n";
}
} catch (const dbc::AccessDeniedException& e) {
std::cerr << "Access denied β check your credentials and/or balance\n";
return 1;
}
return 0;
}| Exception | Base | When |
|---|---|---|
dbc::AccessDeniedException |
std::runtime_error |
Invalid credentials, banned, or insufficient balance |
dbc::ServiceOverloadException |
std::runtime_error |
HTTP 503 / socket service-overload |
# β Build examples preset
cmake --preset examples
cmake --build --preset examples
# β‘ Open any example file and add your credentials
# (look for the your_username / your_password placeholders)
vim examples/get_balance.cpp
# β’ Run integration tests with live credentials
export DBC_USERNAME="your_username"
export DBC_PASSWORD="your_password"
cmake --preset integration
cmake --build --preset integration
ctest --test-dir build/integration --output-on-failure
# β£ Push to repo β GitHub Actions picks up secrets automatically
git pushThis section covers every supported CAPTCHA type, how to build and run the example programs, and ready-to-copy code snippets. Start with the Quick Start below, then use the Type Reference table to find the type you need.
- π¦ Build the library and examples (see Installation)
- π Navigate to the
examples/directory and open the file for the type you need:
# Build examples
cmake --preset examples
cmake --build --preset examples
# Run balance check
./build/examples/examples/get_balance
# Run a normal image CAPTCHA example
./build/examples/examples/ex_normalBefore running any example, open the corresponding .cpp file and set your credentials:
const std::string username = "your_username";
const std::string password = "your_password";The table below maps every supported type to its use case, a code snippet, and the corresponding example file in examples/.
| Type ID | CAPTCHA Type | Use Case | Quick Use | C++ Sample |
|---|---|---|---|---|
| 0 | Standard Image | Basic image CAPTCHA | snippet | open |
| 2 | Deprecated β do not use for new integrations | β | β | |
| 3 | Deprecated β do not use for new integrations | β | β | |
| 4 | reCAPTCHA v2 Token | reCAPTCHA v2 token solving | snippet | open |
| 5 | reCAPTCHA v3 Token | reCAPTCHA v3 with risk scoring | snippet | open |
| 25 | reCAPTCHA v2 Enterprise | reCAPTCHA v2 Enterprise tokens | snippet | open |
| 8 | GeeTest v3 | Geetest v3 verification | snippet | open |
| 9 | GeeTest v4 | Geetest v4 verification | snippet | open |
| 11 | Text CAPTCHA | Text-based question solving | snippet | open |
| 12 | Cloudflare Turnstile | Cloudflare Turnstile token | snippet | open |
| 13 | Audio CAPTCHA | Audio CAPTCHA solving | snippet | open |
| 14 | Lemin | Lemin CAPTCHA | snippet | open |
| 15 | Capy | Capy CAPTCHA | snippet | open |
| 16 | Amazon WAF | Amazon WAF verification | snippet | open |
| 17 | Siara | Siara CAPTCHA | snippet | open |
| 18 | MTCaptcha | MTCaptcha CAPTCHA | snippet | open |
| 19 | Cutcaptcha | Cutcaptcha CAPTCHA | snippet | open |
| 20 | Friendly Captcha | Friendly Captcha | snippet | open |
| 21 | DataDome | Datadome verification | snippet | open |
| 23 | Tencent | Tencent CAPTCHA | snippet | open |
| 24 | ATB | ATB CAPTCHA | snippet | open |
Minimal usage snippet for each supported type. Use these as a starting point and refer to the full example files in examples/ for complete implementations including error handling.
Official description: Supported CAPTCHAs Full sample: example.Normal_Captcha.cpp
auto result = client.decode("path/to/normal_captcha.jpg", 120);Official description: reCAPTCHA Token API (v2) Full sample: example.reCAPTCHA_v2.cpp
const std::string token_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"googlekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
"pageurl": "https://www.google.com/recaptcha/api2/demo"
})";
dbc::Params params = {{"type", "4"}, {"token_params", token_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: reCAPTCHA v3 Full sample: example.reCAPTCHA_v3.cpp
const std::string token_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"googlekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
"pageurl": "https://www.google.com/recaptcha/api2/demo",
"action": "verify",
"min_score": 0.3
})";
dbc::Params params = {{"type", "5"}, {"token_params", token_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: reCAPTCHA v2 Enterprise Full sample: example.reCAPTCHA_v2_Enterprise.cpp
const std::string token_enterprise_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"googlekey": "6LcW4sUUAAAAAEak1SQovtOlJSMl2iUvqCUQnPaQ",
"pageurl": "https://target"
})";
dbc::Params params = {{"type", "25"}, {"token_enterprise_params", token_enterprise_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: GeeTest Full sample: example.Geetest_v3.cpp
const std::string geetest_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"gt": "gt_value",
"challenge": "challenge_value",
"pageurl": "https://target"
})";
dbc::Params params = {{"type", "8"}, {"geetest_params", geetest_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: GeeTest Full sample: example.Geetest_v4.cpp
const std::string geetest_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"captcha_id": "captcha_id",
"pageurl": "https://target"
})";
dbc::Params params = {{"type", "9"}, {"geetest_params", geetest_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: Text CAPTCHA Full sample: example.Textcaptcha.cpp
dbc::Params params = {{"type", "11"}, {"textcaptcha", "What is two plus two?"}};
auto result = client.decode(std::nullopt, 60, params);Official description: Cloudflare Turnstile Full sample: example.Turnstile.cpp
const std::string turnstile_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"sitekey": "0x4AAAAAAAGlwMzq_9z6S9Mh",
"pageurl": "https://clifford.io/demo/cloudflare-turnstile"
})";
dbc::Params params = {{"type", "12"}, {"turnstile_params", turnstile_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: Audio CAPTCHA Full sample: example.Audio.cpp
// The audio file is uploaded directly; the library handles encoding.
dbc::Params params = {{"type", "13"}, {"language", "en"}};
auto result = client.decode("path/to/audio_captcha.mp3", 120, params);Official description: Lemin Full sample: example.Lemin.cpp
const std::string lemin_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"captchaid": "CROPPED_xxx",
"pageurl": "https://target"
})";
dbc::Params params = {{"type", "14"}, {"lemin_params", lemin_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: Capy Full sample: example.Capy.cpp
const std::string capy_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"captchakey": "PUZZLE_xxx",
"api_server": "https://api.capy.me/",
"pageurl": "https://target"
})";
dbc::Params params = {{"type", "15"}, {"capy_params", capy_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: Amazon WAF Full sample: example.Amazon_Waf.cpp
const std::string waf_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"sitekey": "your_aws_waf_sitekey_here",
"pageurl": "https://your-waf-protected-page.example.com",
"iv": "your_iv_here",
"context": "your_context_here"
})";
dbc::Params params = {{"type", "16"}, {"waf_params", waf_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: Siara Full sample: example.Siara.cpp
const std::string siara_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"slideurlid": "slide_master_url_id",
"pageurl": "https://target",
"useragent": "Mozilla/5.0"
})";
dbc::Params params = {{"type", "17"}, {"siara_params", siara_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: MTCaptcha Full sample: example.Mtcaptcha.cpp
const std::string mtcaptcha_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"sitekey": "MTPublic-xxx",
"pageurl": "https://target"
})";
dbc::Params params = {{"type", "18"}, {"mtcaptcha_params", mtcaptcha_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: Cutcaptcha Full sample: example.Cutcaptcha.cpp
const std::string cutcaptcha_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"apikey": "api_key",
"miserykey": "misery_key",
"pageurl": "https://target"
})";
dbc::Params params = {{"type", "19"}, {"cutcaptcha_params", cutcaptcha_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: Friendly Captcha Full sample: example.Friendly.cpp
const std::string friendly_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"sitekey": "FCMG...",
"pageurl": "https://target"
})";
dbc::Params params = {{"type", "20"}, {"friendly_params", friendly_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: DataDome Full sample: example.Datadome.cpp
const std::string datadome_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"pageurl": "https://target",
"captcha_url": "https://target/captcha"
})";
dbc::Params params = {{"type", "21"}, {"datadome_params", datadome_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: Tencent Full sample: example.Tencent.cpp
const std::string tencent_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"appid": "appid",
"pageurl": "https://target"
})";
dbc::Params params = {{"type", "23"}, {"tencent_params", tencent_params}};
auto result = client.decode(std::nullopt, 120, params);Official description: ATB Full sample: example.Atb.cpp
const std::string atb_params = R"({
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"appid": "appid",
"apiserver": "https://cap.aisecurius.com",
"pageurl": "https://target"
})";
dbc::Params params = {{"type", "24"}, {"atb_params", atb_params}};
auto result = client.decode(std::nullopt, 120, params);Full API-level documentation for selected CAPTCHA types: parameter references, payload schemas, request/response formats, token lifespans, and integration notes.
β οΈ Deprecated. Types 2 (Coordinates) and 3 (Image Group) are legacy image-based reCAPTCHA challenge methods that are no longer used at captcha solving. Do not use them for new integrations β use the reCAPTCHA Token API (v2 & v3) instead.
The Token-based API solves reCAPTCHA challenges by returning a token you inject directly into the page form, rather than clicking images. Given a site URL and site key, DBC solves the challenge on its side and returns a token valid for one submission.
- Token Image API: Provided a site URL and site key, the API returns a token that you use to submit the form on the page with the reCAPTCHA challenge.
What's the Token Image API URL? To use the Token Image API you will have to send a HTTP POST Request to http://api.dbcapi.me/api/captcha
What are the POST parameters for the Token image API?
username: Your DBC account usernamepassword: Your DBC account passwordtype=4: Type 4 specifies this is the reCAPTCHA v2 Token APItoken_params=json(payload): the data to access the recaptcha challenge
json payload structure:
proxy: your proxy url and credentials (if any). Examples:proxytype: your proxy connection protocol. Example:HTTPgooglekey: the google recaptcha site key of the website with the recaptcha. Example:6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-pageurl: the url of the page with the recaptcha challenges. This url has to include the path in which the recaptcha is loaded.data-s: Only required for Google search tokens. Use thedata-svalue inside the Google search response html. Not needed for regular tokens.
The proxy parameter is optional, but strongly recommended to prevent token rejection due to IP inconsistencies.
Note: If proxy is provided, proxytype is required.
Full example of token_params:
{
"proxy": "http://127.0.0.1:3128",
"proxytype": "HTTP",
"googlekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
"pageurl": "http://test.com/path_with_recaptcha"
}What's the response from the Token image API?
The token comes in the text field of the dbc::Captcha result. It's valid for one use and has a 2-minute lifespan:
"03AOPBWq_RPO2vLzyk0h8gH0cA2X4v3tpYCPZR6Y4yxKy1s3Eo7CHZRQntxrdsaD2H0e6S..."
This API extends the reCAPTCHA v2 Token API with two additional parameters: action and minimal score (min_score).
reCAPTCHA v3 returns a score from each user, that evaluate if user is a bot or human. Lower scores near to 0 are identified as bot. The action parameter is additional data used to separate different captcha validations (e.g. login, register, sales).
What is action in reCAPTCHA v3?
A parameter that allows processing user actions differently on the website. Find it by inspecting the JavaScript code for grecaptcha.execute calls:
grecaptcha.execute('6Lc2fhwTAAAAAGatXTzFYfvlQMI2T7B6ji8UVV_f', {action: something})The API uses "verify" as default if action is not provided.
What is min_score in reCAPTCHA v3 API?
The minimal score needed for the captcha resolution. We recommend using 0.3 β scores higher than 0.3 are hard to get.
Full example of token_params for v3:
{
"proxy": "http://127.0.0.1:3128",
"proxytype": "HTTP",
"googlekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
"pageurl": "http://test.com/path_with_recaptcha",
"action": "example/action",
"min_score": 0.3
}Amazon WAF Captcha is part of the Intelligent Threat Mitigation system within Amazon AWS. It presents image-alignment challenges that DBC solves by returning a token you set as the aws-waf-token cookie on the target page.
- Official documentation: deathbycaptcha.com/api/amazonwaf
- C++ sample: examples/example.Amazon_Waf.cpp
waf_params payload fields:
| Parameter | Required | Description |
|---|---|---|
proxy |
Optional* | Proxy URL with credentials. E.g. http://user:password@127.0.0.1:3128 |
proxytype |
Required if proxy set | Proxy protocol. Currently only HTTP is supported. |
sitekey |
Required | Amazon WAF site key found in the page's captcha script |
pageurl |
Required | Full URL of the page showing the Amazon WAF challenge |
iv |
Required | Value of the iv parameter found in the captcha script |
context |
Required | Value of the context parameter found in the captcha script |
challengejs |
Optional | URL of the challenge.js script |
captchajs |
Optional | URL of the captcha.js script |
Full example of waf_params:
{
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"sitekey": "AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AH...",
"pageurl": "https://efw47fpad9.execute-api.us-east-1.amazonaws.com/latest",
"iv": "CgAFRjIw2vAAABSM",
"context": "zPT0jOl1rQlUNaldX6LUpn4D6Tl9bJ8VUQ/NrWFxPii..."
}Response: Returns a token string valid for one use with a 1-minute lifespan. Set it as the aws-waf-token cookie on the target page before submitting the form.
Cloudflare Turnstile is a CAPTCHA alternative that protects pages without requiring user interaction in most cases. DBC solves it by returning a token you inject into the target form.
- Official documentation: deathbycaptcha.com/api/turnstile
- C++ sample: examples/example.Turnstile.cpp
turnstile_params payload fields:
| Field | Required | Description |
|---|---|---|
proxy |
Optional | Proxy URL with optional credentials |
proxytype |
Required if proxy set |
Proxy connection protocol. Currently only HTTP is supported. |
sitekey |
Required | The Turnstile site key found in data-sitekey attribute or turnstile.render call |
pageurl |
Required | Full URL of the page hosting the Turnstile challenge |
action |
Optional | Value of data-action attribute or the action option passed to turnstile.render |
π Note: If
proxyis provided,proxytypebecomes required.
Example turnstile_params:
{
"proxy": "http://user:password@127.0.0.1:1234",
"proxytype": "HTTP",
"sitekey": "0x4AAAAAAAGlwMzq_9z6S9Mh",
"pageurl": "https://testsite.com/xxx-test"
}Response: Returns a token string valid for one use with a 2-minute lifespan. Submit it via input[name="cf-turnstile-response"] or pass it to the callback defined in turnstile.render / data-callback.
See RESPONSIBLE_USE.md. This library is provided for legitimate automation against authorized targets only. Do not publish credentials or use this library to bypass security controls without permission.