├── LICENSE ├── README.md ├── api2captcha.go ├── examples ├── AmazonWAFExample.go ├── AtbCAPTCHAExample.go ├── AudioExample.go ├── CanvasExample.go ├── CapyExample.go ├── CloudflareTurnstileExample.go ├── CoordinatesExample.go ├── CutCaptchaExample.go ├── CyberSiARAExample.go ├── DataDomeExample.go ├── FriendlyCaptchaExample.go ├── FriendlyExample.go ├── FunCaptchaExample.go ├── GeeTestExample.go ├── GeeTestV4Example.go ├── GridExample.go ├── KeyCaptchaExample.go ├── LeminExample.go ├── MTCaptchaExample.go ├── NormalExample.go ├── ReCaptchaExample.go ├── RotateExample.go ├── TencentExample.go ├── TextExample.go ├── YandexExample.go ├── assets │ ├── audio-en.mp3 │ ├── canvas.jpg │ ├── grid.jpg │ ├── normal.jpg │ └── rotate.jpg └── internal │ └── Helper.go └── go.mod /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 2captcha 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | # Golang Module for 2Captcha API 11 | The easiest way to quickly integrate [2Captcha] into your code to automate solving of any type of captcha. 12 | Examples of API requests for different captcha types are available on the [Golang captcha solver](https://2captcha.com/lang/go) page. 13 | - [Golang Module for 2Captcha API](#golang-module-for-2captcha-api) 14 | - [Installation](#installation) 15 | - [Configuration](#configuration) 16 | - [Client instance options](#client-instance-options) 17 | - [Solve captcha](#solve-captcha) 18 | - [Captcha options](#captcha-options) 19 | - [Basic example](#basic-example) 20 | - [Normal Captcha](#normal-captcha) 21 | - [Text Captcha](#text-captcha) 22 | - [reCAPTCHA v2](#recaptcha-v2) 23 | - [reCAPTCHA v3](#recaptcha-v3) 24 | - [reCAPTCHA Enterprise](#recaptcha-enterprise) 25 | - [FunCaptcha](#funcaptcha) 26 | - [GeeTest](#geetest) 27 | - [GeeTest V4](#geetest-v4) 28 | - [KeyCaptcha](#keycaptcha) 29 | - [Capy](#capy) 30 | - [Grid](#grid) 31 | - [Canvas](#canvas) 32 | - [ClickCaptcha](#clickcaptcha) 33 | - [Rotate](#rotate) 34 | - [Amazon WAF](#amazon-waf) 35 | - [Cloudflare Turnstile](#cloudflare-turnstile) 36 | - [Lemin Cropped Captcha](#lemin-cropped-captcha) 37 | - [CyberSiARA](#cybersiara) 38 | - [DataDome](#datadome) 39 | - [MTCaptcha](#mtcaptcha) 40 | - [Yandex](#yandex) 41 | - [Tencent](#tencent) 42 | - [atbCAPTCHA](#atbcaptcha) 43 | - [Cutcaptcha](#cutcaptcha) 44 | - [Friendly Captcha](#friendly-captcha) 45 | - [Audio Captcha](#audio-captcha) 46 | - [Other methods](#other-methods) 47 | - [send / getResult](#send--getresult) 48 | - [balance](#balance) 49 | - [report](#report) 50 | - [Proxies](#proxies) 51 | - [Examples](#examples) 52 | - [Get in touch](#get-in-touch) 53 | - [Join the team 👪](#join-the-team-) 54 | - [License](#license) 55 | - [Graphics and Trademarks](#graphics-and-trademarks) 56 | 57 | ## Installation 58 | To install the api client, use this: 59 | 60 | ```bash 61 | go get -u github.com/2captcha/2captcha-go 62 | ``` 63 | 64 | ## Configuration 65 | 66 | Import the module like this: 67 | ```go 68 | import ( 69 | "github.com/2captcha/2captcha-go" 70 | ) 71 | ``` 72 | `Client` instance can be created like this: 73 | ```go 74 | client := api2captcha.NewClient("YOUR_API_KEY") 75 | ``` 76 | There are few options that can be configured: 77 | ```go 78 | client.SoftId = 123 79 | client.Callback = "https://your.site/result-receiver" 80 | client.DefaultTimeout = 120 81 | client.RecaptchaTimeout = 600 82 | client.PollingInterval = 100 83 | ``` 84 | 85 | ### Client instance options 86 | 87 | |Option|Default value|Description| 88 | |---|---|---| 89 | |soft_id|4583|Your software ID obtained after publishing in [2captcha software catalog]| 90 | |callback|-|URL of your web-sever that receives the captcha recognition result. The URl should be first registered in [pingback settings] of your account| 91 | |default_timeout|120|Timeout in seconds for all captcha types except reCAPTCHA. Defines how long the module tries to get the answer from `res.php` API endpoint| 92 | |recaptcha_timeout|600|Timeout for reCAPTCHA in seconds. Defines how long the module tries to get the answer from `res.php` API endpoint| 93 | |polling_interval|10|Interval in seconds between requests to `res.php` API endpoint, setting values less than 5 seconds is not recommended| 94 | 95 | > **IMPORTANT:** once *callback URL* is defined for `client` instance, all methods return only the captcha ID and DO NOT poll the API to get the result. The result will be sent to the callback URL. 96 | 97 | To get the answer manually use [GetResult method](#send--getresult) 98 | 99 | ## Solve captcha 100 | When you submit any image-based captcha use can provide additional options to help 2captcha workers to solve it properly. 101 | 102 | ### Captcha options 103 | |Option|Default Value|Description| 104 | |---|---|---| 105 | |numeric|0|Defines if captcha contains numeric or other symbols [see more info in the API docs][post options]| 106 | |min_len|0|minimal answer length| 107 | |max_len|0|maximum answer length| 108 | |phrase|0|defines if the answer contains multiple words or not| 109 | |case_sensitive|0|defines if the answer is case sensitive| 110 | |calc|0|defines captcha requires calculation| 111 | |lang|-|defines the captcha language, see the [list of supported languages] | 112 | |hint_img|-|an image with hint shown to workers with the captcha| 113 | |hint_text|-|hint or task text shown to workers with the captcha| 114 | 115 | Below you can find basic examples for every captcha type, check out the code below. 116 | 117 | ### Basic example 118 | Example below shows a basic solver call example with error handling. 119 | 120 | ```go 121 | captcha := api2captcha.Normal{ 122 | File: "/path/to/normal.jpg", 123 | } 124 | 125 | code, err := client.Solve(captcha.ToRequest()) 126 | if err != nil { 127 | if err == api2captcha.ErrTimeout { 128 | log.Fatal("Timeout"); 129 | } else if err == api2captcha.ErrApi { 130 | log.Fatal("API error"); 131 | } else if err == api2captcha.ErrNetwork { 132 | log.Fatal("Network error"); 133 | } else { 134 | log.Fatal(err); 135 | } 136 | } 137 | fmt.Println("code "+code) 138 | ``` 139 | 140 | ### Normal Captcha 141 | 142 | [API method description.](https://2captcha.com/2captcha-api#solving_normal_captcha) 143 | 144 | To bypass a normal captcha (distorted text on image) use the following method. This method also can be used to recognize any text on the image. 145 | 146 | ```go 147 | captcha:= api2captcha.Normal{ 148 | File: "/path/to/normal.jpg", 149 | Numeric: 4, 150 | MinLen: 4, 151 | MaxLen: 20, 152 | Phrase: true, 153 | CaseSensitive: true, 154 | Lang: "en", 155 | HintImgFile: "/path/to/hint.jpg", 156 | HintText: "Type red symbols", 157 | } 158 | ``` 159 | 160 | ### Text Captcha 161 | 162 | [API method description.](https://2captcha.com/2captcha-api#solving_text_captcha) 163 | 164 | This method can be used to bypass a captcha that requires to answer a question provided in clear text. 165 | 166 | ```go 167 | captcha:= api2captcha.Text{ 168 | Text: "If tomorrow is Saturday, what day is today?", 169 | Lang: "en", 170 | } 171 | ``` 172 | 173 | ### reCAPTCHA v2 174 | 175 | [API method description.](https://2captcha.com/2captcha-api#solving_recaptchav2_new) 176 | 177 | Use this method to solve reCAPTCHA V2 and obtain a token to bypass the protection. 178 | 179 | ```go 180 | captcha := api2captcha.ReCaptcha{ 181 | SiteKey: "6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-", 182 | Url: "https://mysite.com/page/with/recaptcha", 183 | Invisible: true, 184 | Action: "verify", 185 | } 186 | req := captcha.ToRequest() 187 | req.SetProxy("HTTPS", "login:password@IP_address:PORT") 188 | code, err := client.Solve(req) 189 | ``` 190 | 191 | ### reCAPTCHA v3 192 | 193 | [API method description.](https://2captcha.com/2captcha-api#solving_recaptchav3) 194 | 195 | This method provides reCAPTCHA V3 solver and returns a token. 196 | 197 | ```go 198 | captcha := api2captcha.ReCaptcha{ 199 | SiteKey: "6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-", 200 | Url: "https://mysite.com/page/with/recaptcha", 201 | Version: "v3", 202 | Action: "verify", 203 | Score: 0.3, 204 | } 205 | req := captcha.ToRequest() 206 | req.SetProxy("HTTPS", "login:password@IP_address:PORT") 207 | code, err := client.Solve(req) 208 | ``` 209 | 210 | ### reCAPTCHA Enterprise 211 | 212 | [API method description.](https://2captcha.com/2captcha-api#solving_recaptcha_enterprise) 213 | 214 | reCAPTCHA Enterprise can be used as reCAPTCHA V2 and reCAPTCHA V3. Below is a usage example for both versions. 215 | 216 | ```go 217 | // reCAPTCHA V2 218 | captcha:= api2captcha.ReCaptcha({ 219 | SiteKey: "6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-", 220 | Url: "https://mysite.com/page/with/recaptcha", 221 | Invisible: true, 222 | Action: "verify", 223 | Enterprise: true, 224 | }) 225 | 226 | // reCAPTCHA V3 227 | captcha := api2captcha.ReCaptcha{ 228 | SiteKey: "6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-", 229 | Url: "https://mysite.com/page/with/recaptcha", 230 | Version: "v3", 231 | Action: "verify", 232 | Score: 0.3, 233 | Enterprise: true, 234 | } 235 | 236 | req := captcha.ToRequest() 237 | req.SetProxy("HTTPS", "login:password@IP_address:PORT") 238 | code, err := client.Solve(req) 239 | ``` 240 | 241 | ### FunCaptcha 242 | 243 | [API method description.](https://2captcha.com/2captcha-api#solving_funcaptcha_new) 244 | 245 | FunCaptcha (Arkoselabs) solving method. Returns a token. 246 | 247 | ```go 248 | captcha := api2captcha.FunCaptcha{ 249 | SiteKey: "69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC", 250 | Url: "https://mysite.com/page/with/funcaptcha", 251 | Surl: "https://client-api.arkoselabs.com", 252 | UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36", 253 | Data: map[string]string{"anyKey":"anyValue"}, 254 | } 255 | req := captcha.ToRequest() 256 | req.SetProxy("HTTPS", "login:password@IP_address:PORT") 257 | code, err := client.Solve(req) 258 | ``` 259 | 260 | ### GeeTest 261 | 262 | [API method description.](https://2captcha.com/2captcha-api#solving_geetest) 263 | 264 | Method to solve GeeTest puzzle captcha. Returns a set of tokens as JSON. 265 | 266 | ```go 267 | captcha := api2captcha.GeeTest{ 268 | GT: "f2ae6cadcf7886856696502e1d55e00c", 269 | ApiServer: "api-na.geetest.com", 270 | Challenge: "12345678abc90123d45678ef90123a456b", 271 | Url: "https://mysite.com/captcha.html", 272 | } 273 | req := captcha.ToRequest() 274 | req.SetProxy("HTTPS", "login:password@IP_address:PORT") 275 | code, err := client.Solve(req) 276 | ``` 277 | 278 | ### GeeTest V4 279 | 280 | [API method description.](https://2captcha.com/2captcha-api#geetest-v4) 281 | 282 | Use this method to solve GeeTest v4. Returns the response in JSON. 283 | 284 | ```go 285 | captcha:= api2captcha.GeeTestV4{ 286 | CaptchaId: "e392e1d7fd421dc63325744d5a2b9c73", 287 | Url: "https://www.site.com/page/", 288 | } 289 | ``` 290 | 291 | ### KeyCaptcha 292 | 293 | [API method description.](https://2captcha.com/2captcha-api#solving_keycaptcha) 294 | 295 | Token-based method to solve KeyCaptcha. 296 | 297 | ```go 298 | captcha:= api2captcha.KeyCaptcha{ 299 | UserId: 10, 300 | SessionId: "493e52c37c10c2bcdf4a00cbc9ccd1e8", 301 | WebServerSign: "9006dc725760858e4c0715b835472f22", 302 | WebServerSign2: "9006dc725760858e4c0715b835472f22", 303 | Url: "https://www.keycaptcha.ru/demo-magnetic/", 304 | } 305 | req := captchaToRequest() 306 | req.SetProxy("HTTPS", "login:password@IP_address:PORT") 307 | code, err := client.Solve(req) 308 | ``` 309 | 310 | ### Capy 311 | 312 | [API method description.](https://2captcha.com/2captcha-api#solving_capy) 313 | 314 | Token-based method to bypass Capy puzzle captcha. 315 | 316 | ```go 317 | captcha:= api2captcha.Capy{ 318 | SiteKey: "PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v", 319 | Url: "https://www.mysite.com/captcha/", 320 | } 321 | req := captchaToRequest() 322 | req.SetProxy("HTTPS", "login:password@IP_address:PORT") 323 | code, err := client.Solve(req) 324 | ``` 325 | 326 | ### Grid 327 | 328 | [API method description.](https://2captcha.com/2captcha-api#grid) 329 | 330 | Grid method is originally called Old reCAPTCHA V2 method. The method can be used to bypass any type of captcha where you can apply a grid on image and need to click specific grid boxes. Returns numbers of boxes. 331 | 332 | ```go 333 | captcha:= api2captcha.Grid{ 334 | File: "path/to/captcha.jpg", 335 | Rows: 3, 336 | Cols: 3, 337 | PreviousId: 0, 338 | CanSkip: false, 339 | Lang: "en", 340 | HintImageFile: "path/to/hint.jpg", 341 | HintText: "Select all images with an Orange", 342 | } 343 | ``` 344 | 345 | ### Canvas 346 | 347 | [API method description.](https://2captcha.com/2captcha-api#canvas) 348 | 349 | Canvas method can be used when you need to draw a line around an object on image. Returns a set of points' coordinates to draw a polygon. 350 | 351 | ```go 352 | captcha:= api2captcha.Canvas{ 353 | File: "path/to/captcha.jpg", 354 | PreviousId: 0, 355 | CanSkip: false, 356 | Lang: "en", 357 | HintImageFile: "path/to/hint.jpg", 358 | HintText: "Draw around apple", 359 | } 360 | ``` 361 | 362 | ### ClickCaptcha 363 | 364 | [API method description.](https://2captcha.com/2captcha-api#coordinates) 365 | 366 | ClickCaptcha method returns coordinates of points on captcha image. Can be used if you need to click on particular points on the image. 367 | 368 | ```go 369 | captcha:= api2captcha.Coordinates{ 370 | File: "path/to/captcha.jpg", 371 | Lang: "en", 372 | HintImageFile: "path/to/hint.jpg", 373 | HintText: "Connect the dots", 374 | } 375 | ``` 376 | 377 | ### Rotate 378 | 379 | [API method description.](https://2captcha.com/2captcha-api#solving_rotatecaptcha) 380 | 381 | This method can be used to solve a captcha that asks to rotate an object. Mostly used to bypass FunCaptcha. Returns the rotation angle. 382 | 383 | ```go 384 | captcha:= api2captcha.Rotate{ 385 | File: "path/to/captcha.jpg", 386 | Angle: 15, 387 | Lang: "en", 388 | HintImageFile: "path/to/hint.jpg", 389 | HintText: "Put the images in the correct way", 390 | } 391 | ``` 392 | 393 | ### Amazon WAF 394 | 395 | [API method description.](https://2captcha.com/2captcha-api#amazon-waf) 396 | 397 | Use this method to solve Amazon WAF Captcha also known as AWS WAF Captcha is a part of Intelligent threat mitigation for Amazon AWS. Returns JSON with the token. 398 | 399 | ```go 400 | captcha:= api2captcha.AmazonWAF { 401 | Iv: "CgAHbCe2GgAAAAAj", 402 | SiteKey: "0x1AAAAAAAAkg0s2VIOD34y5", 403 | Url: "https://non-existent-example.execute-api.us-east-1.amazonaws.com/latest", 404 | Context: "9BUgmlm48F92WUoqv97a49ZuEJJ50TCk9MVr3C7WMtQ0X6flVbufM4n8mjFLmbLVAPgaQ1Jydeaja94iAS49ljb", 405 | ChallengeScript: "https://41bcdd4fb3cb.610cd090.us-east-1.token.awswaf.com/41bcdd4fb3cb/0d21de737ccb/cd77baa6c832/challenge.js" 406 | CaptchaScript: "https://41bcdd4fb3cb.610cd090.us-east-1.captcha.awswaf.com/41bcdd4fb3cb/0d21de737ccb/cd77baa6c832/captcha.js" 407 | } 408 | ``` 409 | 410 | ### Cloudflare Turnstile 411 | 412 | [API method description.](https://2captcha.com/2captcha-api#turnstile) 413 | 414 | Use this method to solve Cloudflare Turnstile. Returns JSON with the token. 415 | 416 | ```go 417 | captcha:= api2captcha.CloudflareTurnstile{ 418 | SiteKey: "0x1AAAAAAAAkg0s2VIOD34y5", 419 | Url: "http://mysite.com/", 420 | } 421 | ``` 422 | 423 | ### Lemin Cropped Captcha 424 | 425 | [API method description.](https://2captcha.com/2captcha-api#lemin) 426 | 427 | Use this method to solve Lemin Captcha challenge. Returns JSON with answer containing the following values: answer, challenge_id. 428 | 429 | ```go 430 | captcha:= Lemin{ 431 | CaptchaId: "CROPPED_3dfdd5c_d1872b526b794d83ba3b365eb15a200b", 432 | Url: "https://www.site.com/page/", 433 | DivId: "lemin-cropped-captcha", 434 | ApiServer: "api.leminnow.com", 435 | } 436 | ``` 437 | 438 | ### CyberSiARA 439 | 440 | [API method description.](https://2captcha.com/2captcha-api#cybersiara) 441 | 442 | Use this method to solve CyberSiARA and obtain a token to bypass the protection. 443 | ```go 444 | captcha:= api2captcha.CyberSiARA{ 445 | MasterUrlId: "12333-3123123", 446 | Url: "https://test.com", 447 | UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36", 448 | } 449 | ``` 450 | 451 | ### DataDome 452 | 453 | [API method description.](https://2captcha.com/2captcha-api#datadome) 454 | 455 | Use this method to solve DataDome and obtain a token to bypass the protection. 456 | 457 | > [!IMPORTANT] 458 | > To solve the DataDome captcha, you must use a proxy. It is recommended to use [residential proxies]. 459 | 460 | 461 | ```go 462 | captcha:= api2captcha.DataDome{ 463 | Url: "https://test.com", 464 | CaptchaUrl: "https://test.com/captcha/", 465 | Proxytype: "http", 466 | Proxy: "proxyuser:strongPassword@123.123.123.123:3128", 467 | UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36", 468 | } 469 | ``` 470 | 471 | ### MTCaptcha 472 | 473 | [API method description.](https://2captcha.com/2captcha-api#mtcaptcha) 474 | 475 | Use this method to solve MTCaptcha and obtain a token to bypass the protection. 476 | ```go 477 | captcha:= api2captcha.MTCaptcha{ 478 | Url: "https://service.mtcaptcha.com/mtcv1/demo/index.html", 479 | SiteKey: "MTPublic-DemoKey9M", 480 | } 481 | ``` 482 | 483 | ### Yandex 484 | Use this method to solve Yandex and obtain a token to bypass the protection. 485 | ```go 486 | captcha:= api2captcha.Yandex{ 487 | Url: "https://example.com", 488 | SiteKey: "Y5Lh0tiycconMJGsFd3EbbuNKSp1yaZESUOIHfeV", 489 | } 490 | ``` 491 | 492 | ### Tencent 493 | 494 | [API method description.](https://2captcha.com/2captcha-api#tencent) 495 | 496 | Use this method to solve Tencent and obtain a token to bypass the protection. 497 | ```go 498 | tencentCaptcha := api2captcha.Tencent{ 499 | AppId: "2092215077", 500 | Url: "http://lcec.lclog.cn/cargo/NewCargotracking?blno=BANR01XMHB0004&selectstate=BLNO", 501 | } 502 | ``` 503 | 504 | ### atbCAPTCHA 505 | 506 | [API method description.](https://2captcha.com/2captcha-api#atb-captcha) 507 | 508 | Use this method to solve atbCAPTCHA and obtain a token to bypass the protection. 509 | ```go 510 | atbCaptcha := api2captcha.AtbCAPTCHA{ 511 | AppId: "af23e041b22d000a11e22a230fa8991c", 512 | Url: "https://www.playzone.vip/", 513 | ApiServer: "https://cap.aisecurius.com", 514 | } 515 | ``` 516 | 517 | ### Cutcaptcha 518 | 519 | [API method description.](https://2captcha.com/2captcha-api#cutcaptcha) 520 | 521 | Use this method to solve Cutcaptcha and obtain a token to bypass the protection. 522 | ```go 523 | captcha:= api2captcha.Cutcaptcha{ 524 | MiseryKey: "a1488b66da00bf332a1488993a5443c79047e752", 525 | DataApiKey: "SAb83IIB", 526 | Url: "https://example.cc/foo/bar.html", 527 | } 528 | ``` 529 | 530 | ### Friendly Captcha 531 | 532 | [API method description.](https://2captcha.com/2captcha-api#friendly-captcha) 533 | 534 | Use this method to solve Friendly Captcha and obtain a token to bypass the protection. 535 | ```go 536 | captcha:= api2captcha.Friendly{ 537 | Url: "https://example.com", 538 | SiteKey: "2FZFEVS1FZCGQ9", 539 | } 540 | ``` 541 | 542 | ### Audio Captcha 543 | 544 | [API method description.](https://2captcha.com/2captcha-api#audio) 545 | 546 | Use this method to solve Audio captcha and obtain a token to bypass the protection. 547 | ```go 548 | audio := api2captcha.Audio{ 549 | Base64: fileBase64Str, 550 | Lang: "en", 551 | } 552 | ``` 553 | 554 | ## Other methods 555 | 556 | ### Send / GetResult 557 | These methods can be used for manual captcha submission and answer polling. 558 | 559 | ```go 560 | id, err := client.Send(captchaToRequest()) 561 | if err != nil { 562 | log.Fatal(err); 563 | } 564 | 565 | time.Sleep(10 * time.Second) 566 | 567 | code, err := client.GetResult(id) 568 | if err != nil { 569 | log.Fatal(err); 570 | } 571 | 572 | if code == nil { 573 | log.Fatal("Not ready") 574 | } 575 | 576 | fmt.Println("code "+*code) 577 | ``` 578 | 579 | ### balance 580 | 581 | [API method description.](https://2captcha.com/2captcha-api#additional-methods) 582 | 583 | Use this method to get your account's balance 584 | 585 | ```go 586 | balance, err := client.GetBalance() 587 | if err != nil { 588 | log.Fatal(err); 589 | } 590 | ``` 591 | ### report 592 | 593 | [API method description.](https://2captcha.com/2captcha-api#complain) 594 | 595 | Use this method to report good or bad captcha answer. 596 | 597 | ```go 598 | err := client.Report(id, true) // solved correctly 599 | err := client.Report(id, false) // solved incorrectly 600 | ``` 601 | 602 | ## Error Handling 603 | 604 | When using the 2Captcha API, it's important to handle errors properly to ensure smooth interaction with the service. Below is an example of error handling in the `2captcha-go` library: 605 | 606 | ```go 607 | func main() { 608 | result, err := client.Text("If tomorrow is Saturday, what day is today?") 609 | if err != nil { 610 | switch e := err.(type) { 611 | case *api.ValidationException: 612 | // Invalid parameters passed 613 | log.Fatalf("Validation error: %v", e) 614 | case *api.NetworkException: 615 | // Network error occurred 616 | log.Fatalf("Network error: %v", e) 617 | case *api.ApiException: 618 | // API responded with an error 619 | log.Fatalf("API error: %v", e) 620 | case *api.TimeoutException: 621 | // CAPTCHA is not solved within the expected time 622 | log.Fatalf("Timeout error: %v", e) 623 | default: 624 | // Unknown error 625 | log.Fatalf("Unexpected error: %v", err) 626 | } 627 | } 628 | 629 | fmt.Printf("CAPTCHA solved! Result: %s\n", result.Text) 630 | } 631 | ``` 632 | 633 | ## Proxies 634 | You can pass your proxy as an additional argument for methods: recaptcha, funcaptcha, geetest, geetest v4, keycaptcha, capy puzzle, lemin, turnstile, amazon waf, CyberSiARA, DataDome, MTCaptcha and etc. The proxy will be forwarded to the API to solve the captcha. 635 | 636 | We have our own proxies that we can offer you. [Buy residential proxies](https://2captcha.com/proxy/residential-proxies) for avoid restrictions and blocks. [Quick start](https://2captcha.com/proxy?openAddTrafficModal=true). 637 | 638 | ## Examples 639 | 640 | Examples of solving all supported captcha types are located in the [examples] directory. 641 | 642 | ## Get in touch 643 | 644 | 645 | 646 | 647 | ## Join the team 👪 648 | 649 | There are many ways to contribute, of which development is only one! Find your next job. Open positions: AI experts, scrapers, developers, technical support, and much more! 😍 650 | 651 | 652 | 653 | ## License 654 | 655 | The code in this repository is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more details. 656 | 657 | ### Graphics and Trademarks 658 | 659 | The graphics and trademarks included in this repository are not covered by the MIT License. Please contact support for permissions regarding the use of these materials. 660 | 661 | 662 | 663 | [2Captcha]: https://2captcha.com/ 664 | [2captcha software catalog]: https://2captcha.com/software 665 | [pingback settings]: https://2captcha.com/setting/pingback 666 | [post options]: https://2captcha.com/2captcha-api#normal_post 667 | [list of supported languages]: https://2captcha.com/2captcha-api#language 668 | [residential proxies]: https://2captcha.com/proxy/residential-proxies 669 | [examples]: ./examples/ 670 | -------------------------------------------------------------------------------- /api2captcha.go: -------------------------------------------------------------------------------- 1 | package api2captcha 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "io" 7 | "mime/multipart" 8 | "net/http" 9 | "net/url" 10 | "os" 11 | "path/filepath" 12 | "strconv" 13 | "strings" 14 | "time" 15 | ) 16 | 17 | const ( 18 | BaseURL = "https://2captcha.com" 19 | DefaultSoftId = 4583 20 | ) 21 | 22 | type ( 23 | Request struct { 24 | Params map[string]string 25 | Files map[string]string 26 | } 27 | 28 | Client struct { 29 | BaseURL *url.URL 30 | ApiKey string 31 | SoftId int 32 | Callback string 33 | DefaultTimeout int 34 | RecaptchaTimeout int 35 | PollingInterval int 36 | 37 | httpClient *http.Client 38 | } 39 | 40 | Canvas struct { 41 | File string 42 | Base64 string 43 | PreviousId int 44 | CanSkip bool 45 | Lang string 46 | HintText string 47 | HintImageBase64 string 48 | HintImageFile string 49 | } 50 | 51 | Capy struct { 52 | SiteKey string 53 | Url string 54 | ApiServer string 55 | } 56 | 57 | Coordinates struct { 58 | File string 59 | Base64 string 60 | Lang string 61 | HintText string 62 | HintImageBase64 string 63 | HintImageFile string 64 | } 65 | 66 | FunCaptcha struct { 67 | SiteKey string 68 | Url string 69 | Surl string 70 | UserAgent string 71 | Data map[string]string 72 | } 73 | 74 | GeeTest struct { 75 | GT string 76 | Challenge string 77 | Url string 78 | ApiServer string 79 | } 80 | 81 | Grid struct { 82 | File string 83 | Base64 string 84 | Rows int 85 | Cols int 86 | PreviousId int 87 | CanSkip bool 88 | Lang string 89 | HintText string 90 | HintImageBase64 string 91 | HintImageFile string 92 | } 93 | 94 | HCaptcha struct { 95 | SiteKey string 96 | Url string 97 | } 98 | 99 | KeyCaptcha struct { 100 | UserId int 101 | SessionId string 102 | WebServerSign string 103 | WebServerSign2 string 104 | Url string 105 | } 106 | 107 | Normal struct { 108 | File string 109 | Base64 string 110 | Phrase bool 111 | CaseSensitive bool 112 | Calc bool 113 | Numberic int 114 | MinLen int 115 | MaxLen int 116 | Lang string 117 | HintText string 118 | HintImageBase64 string 119 | HintImageFile string 120 | } 121 | 122 | ReCaptcha struct { 123 | SiteKey string 124 | Url string 125 | Invisible bool 126 | Enterprise bool 127 | Version string 128 | Action string 129 | DataS string 130 | Score float64 131 | } 132 | 133 | Rotate struct { 134 | Base64 string 135 | File string 136 | Files []string 137 | Angle int 138 | Lang string 139 | HintText string 140 | HintImageBase64 string 141 | HintImageFile string 142 | } 143 | 144 | Text struct { 145 | Text string 146 | Lang string 147 | } 148 | 149 | AmazonWAF struct { 150 | Iv string 151 | SiteKey string 152 | Url string 153 | Context string 154 | ChallengeScript string 155 | CaptchaScript string 156 | } 157 | 158 | GeeTestV4 struct { 159 | CaptchaId string 160 | Url string 161 | ApiServer string 162 | Challenge string 163 | } 164 | 165 | Lemin struct { 166 | CaptchaId string 167 | DivId string 168 | Url string 169 | ApiServer string 170 | } 171 | 172 | CloudflareTurnstile struct { 173 | SiteKey string 174 | Url string 175 | Data string 176 | PageData string 177 | Action string 178 | UserAgent string 179 | } 180 | 181 | CyberSiARA struct { 182 | MasterUrlId string 183 | Url string 184 | UserAgent string 185 | } 186 | 187 | DataDome struct { 188 | Url string 189 | CaptchaUrl string 190 | Proxytype string 191 | Proxy string 192 | UserAgent string 193 | } 194 | 195 | MTCaptcha struct { 196 | SiteKey string 197 | Url string 198 | } 199 | 200 | Yandex struct { 201 | Url string 202 | SiteKey string 203 | } 204 | 205 | Friendly struct { 206 | Url string 207 | SiteKey string 208 | } 209 | 210 | CutCaptcha struct { 211 | MiseryKey string 212 | DataApiKey string 213 | Url string 214 | } 215 | 216 | Tencent struct { 217 | AppId string 218 | Url string 219 | } 220 | 221 | AtbCAPTCHA struct { 222 | AppId string 223 | ApiServer string 224 | Url string 225 | } 226 | 227 | Audio struct { 228 | Base64 string 229 | Lang string 230 | } 231 | ) 232 | 233 | var ( 234 | ErrNetwork = errors.New("api2captcha: Network failure") 235 | ErrApi = errors.New("api2captcha: API error") 236 | ErrTimeout = errors.New("api2captcha: Request timeout") 237 | ) 238 | 239 | func NewClient(apiKey string) *Client { 240 | base, _ := url.Parse(BaseURL) 241 | return &Client{ 242 | BaseURL: base, 243 | ApiKey: apiKey, 244 | SoftId: DefaultSoftId, 245 | DefaultTimeout: 120, 246 | PollingInterval: 10, 247 | RecaptchaTimeout: 600, 248 | httpClient: http.DefaultClient, 249 | } 250 | } 251 | 252 | func NewClientExt(apiKey string, client *http.Client) *Client { 253 | base, _ := url.Parse(BaseURL) 254 | return &Client{ 255 | BaseURL: base, 256 | ApiKey: apiKey, 257 | DefaultTimeout: 120, 258 | PollingInterval: 10, 259 | RecaptchaTimeout: 600, 260 | httpClient: client, 261 | } 262 | } 263 | 264 | func (c *Client) res(req Request) (*string, error) { 265 | 266 | rel := &url.URL{Path: "/res.php"} 267 | uri := c.BaseURL.ResolveReference(rel) 268 | 269 | req.Params["key"] = c.ApiKey 270 | c.httpClient.Timeout = time.Duration(c.DefaultTimeout) * time.Second 271 | 272 | var resp *http.Response = nil 273 | 274 | values := url.Values{} 275 | for key, val := range req.Params { 276 | values.Add(key, val) 277 | } 278 | uri.RawQuery = values.Encode() 279 | 280 | var err error = nil 281 | resp, err = c.httpClient.Get(uri.String()) 282 | if err != nil { 283 | return nil, ErrNetwork 284 | } 285 | 286 | defer resp.Body.Close() 287 | body := &bytes.Buffer{} 288 | _, err = body.ReadFrom(resp.Body) 289 | if err != nil { 290 | return nil, err 291 | } 292 | data := body.String() 293 | 294 | if resp.StatusCode != http.StatusOK { 295 | return nil, ErrApi 296 | } 297 | 298 | if strings.HasPrefix(data, "ERROR_") { 299 | return nil, ErrApi 300 | } 301 | 302 | return &data, nil 303 | } 304 | 305 | func (c *Client) resAction(action string) (*string, error) { 306 | req := Request{ 307 | Params: map[string]string{"action": action}, 308 | } 309 | 310 | return c.res(req) 311 | } 312 | 313 | func (c *Client) Send(req Request) (string, error) { 314 | 315 | rel := &url.URL{Path: "/in.php"} 316 | uri := c.BaseURL.ResolveReference(rel) 317 | 318 | req.Params["key"] = c.ApiKey 319 | 320 | c.httpClient.Timeout = time.Duration(c.DefaultTimeout) * time.Second 321 | 322 | var resp *http.Response = nil 323 | if req.Files != nil && len(req.Files) > 0 { 324 | 325 | body := &bytes.Buffer{} 326 | writer := multipart.NewWriter(body) 327 | 328 | for name, path := range req.Files { 329 | file, err := os.Open(path) 330 | if err != nil { 331 | return "", err 332 | } 333 | defer file.Close() 334 | 335 | part, err := writer.CreateFormFile(name, filepath.Base(path)) 336 | if err != nil { 337 | return "", err 338 | } 339 | _, err = io.Copy(part, file) 340 | } 341 | 342 | for key, val := range req.Params { 343 | _ = writer.WriteField(key, val) 344 | } 345 | 346 | err := writer.Close() 347 | if err != nil { 348 | return "", err 349 | } 350 | 351 | request, err := http.NewRequest("POST", uri.String(), body) 352 | if err != nil { 353 | return "", err 354 | } 355 | 356 | request.Header.Set("Content-Type", writer.FormDataContentType()) 357 | 358 | resp, err = c.httpClient.Do(request) 359 | if err != nil { 360 | return "", ErrNetwork 361 | } 362 | } else { 363 | values := url.Values{} 364 | for key, val := range req.Params { 365 | values.Add(key, val) 366 | } 367 | 368 | var err error = nil 369 | resp, err = c.httpClient.PostForm(uri.String(), values) 370 | if err != nil { 371 | return "", ErrNetwork 372 | } 373 | } 374 | 375 | defer resp.Body.Close() 376 | body := &bytes.Buffer{} 377 | _, err := body.ReadFrom(resp.Body) 378 | if err != nil { 379 | return "", err 380 | } 381 | data := body.String() 382 | 383 | if resp.StatusCode != http.StatusOK { 384 | return "", ErrApi 385 | } 386 | 387 | if strings.HasPrefix(data, "ERROR_") { 388 | return "", ErrApi 389 | } 390 | 391 | if !strings.HasPrefix(data, "OK|") { 392 | return "", ErrApi 393 | } 394 | 395 | return data[3:], nil 396 | } 397 | 398 | func (c *Client) Solve(req Request) (string, string, error) { 399 | if c.Callback != "" { 400 | _, ok := req.Params["pingback"] 401 | if !ok { 402 | // set default pingback 403 | req.Params["pingback"] = c.Callback 404 | } 405 | } 406 | 407 | pingback, hasPingback := req.Params["pingback"] 408 | if pingback == "" { 409 | delete(req.Params, "pingback") 410 | hasPingback = false 411 | } 412 | 413 | _, ok := req.Params["soft_id"] 414 | if c.SoftId != 0 && !ok { 415 | req.Params["soft_id"] = strconv.FormatInt(int64(c.SoftId), 10) 416 | } 417 | 418 | id, err := c.Send(req) 419 | if err != nil { 420 | return "", "", err 421 | } 422 | 423 | // don't wait for result if Callback is used 424 | if hasPingback { 425 | return "", id, nil 426 | } 427 | 428 | timeout := c.DefaultTimeout 429 | if req.Params["method"] == "userrecaptcha" { 430 | timeout = c.RecaptchaTimeout 431 | } 432 | 433 | token, err := c.WaitForResult(id, timeout, c.PollingInterval) 434 | if err != nil { 435 | return "", "", err 436 | } 437 | 438 | return token, id, nil 439 | } 440 | 441 | func (c *Client) WaitForResult(id string, timeout int, interval int) (string, error) { 442 | 443 | start := time.Now() 444 | now := start 445 | for now.Sub(start) < (time.Duration(timeout) * time.Second) { 446 | 447 | time.Sleep(time.Duration(interval) * time.Second) 448 | 449 | code, err := c.GetResult(id) 450 | if err == nil && code != nil { 451 | return *code, nil 452 | } 453 | 454 | // ignore network errors 455 | if err != nil && err != ErrNetwork { 456 | return "", err 457 | } 458 | 459 | now = time.Now() 460 | } 461 | 462 | return "", ErrTimeout 463 | } 464 | 465 | func (c *Client) GetResult(id string) (*string, error) { 466 | req := Request{ 467 | Params: map[string]string{"action": "get", "id": id}, 468 | } 469 | 470 | data, err := c.res(req) 471 | if err != nil { 472 | return nil, err 473 | } 474 | 475 | if *data == "CAPCHA_NOT_READY" { 476 | return nil, nil 477 | } 478 | 479 | if !strings.HasPrefix(*data, "OK|") { 480 | return nil, ErrApi 481 | } 482 | 483 | reply := (*data)[3:] 484 | return &reply, nil 485 | } 486 | 487 | func (c *Client) GetBalance() (float64, error) { 488 | data, err := c.resAction("getbalance") 489 | if err != nil { 490 | return 0.0, err 491 | } 492 | 493 | return strconv.ParseFloat(*data, 64) 494 | } 495 | 496 | func (c *Client) Report(id string, correct bool) error { 497 | req := Request{ 498 | Params: map[string]string{"id": id}, 499 | } 500 | if correct { 501 | req.Params["action"] = "reportgood" 502 | } else { 503 | req.Params["action"] = "reportbad" 504 | } 505 | 506 | _, err := c.res(req) 507 | return err 508 | } 509 | 510 | func (req *Request) SetProxy(proxyType string, uri string) { 511 | req.Params["proxytype"] = proxyType 512 | req.Params["proxy"] = uri 513 | } 514 | 515 | func (req *Request) SetSoftId(softId int) { 516 | req.Params["soft_id"] = strconv.FormatInt(int64(softId), 10) 517 | } 518 | 519 | func (req *Request) SetCallback(callback string) { 520 | req.Params["pingback"] = callback 521 | } 522 | 523 | func (c *Canvas) ToRequest() Request { 524 | req := Request{ 525 | Params: map[string]string{"canvas": "1", "recaptcha": "1"}, 526 | Files: map[string]string{}, 527 | } 528 | if c.File != "" { 529 | req.Files["file"] = c.File 530 | req.Params["method"] = "post" 531 | } 532 | if c.Base64 != "" { 533 | req.Params["body"] = c.Base64 534 | req.Params["method"] = "base64" 535 | } 536 | if c.PreviousId != 0 { 537 | req.Params["previousID"] = strconv.FormatInt(int64(c.PreviousId), 10) 538 | } 539 | if c.CanSkip { 540 | req.Params["can_no_answer"] = "1" 541 | } 542 | if c.Lang != "" { 543 | req.Params["lang"] = c.Lang 544 | } 545 | if c.HintText != "" { 546 | req.Params["textinstructions"] = c.HintText 547 | } 548 | if c.HintImageBase64 != "" { 549 | req.Params["imginstructions"] = c.HintImageBase64 550 | } 551 | if c.HintImageFile != "" { 552 | req.Files["imginstructions"] = c.HintImageFile 553 | } 554 | 555 | return req 556 | } 557 | 558 | func (c *Normal) ToRequest() Request { 559 | req := Request{ 560 | Params: map[string]string{}, 561 | Files: map[string]string{}, 562 | } 563 | if c.File != "" { 564 | req.Files["file"] = c.File 565 | req.Params["method"] = "post" 566 | } 567 | if c.Base64 != "" { 568 | req.Params["body"] = c.Base64 569 | req.Params["method"] = "base64" 570 | } 571 | 572 | if c.Phrase { 573 | req.Params["phrase"] = "1" 574 | } 575 | if c.CaseSensitive { 576 | req.Params["regsense"] = "1" 577 | } 578 | if c.Calc { 579 | req.Params["calc"] = "1" 580 | } 581 | if c.Numberic != 0 { 582 | req.Params["numeric"] = strconv.FormatInt(int64(c.Numberic), 10) 583 | } 584 | if c.MinLen != 0 { 585 | req.Params["min_len"] = strconv.FormatInt(int64(c.MinLen), 10) 586 | } 587 | if c.MaxLen != 0 { 588 | req.Params["max_len"] = strconv.FormatInt(int64(c.MaxLen), 10) 589 | } 590 | 591 | if c.Lang != "" { 592 | req.Params["lang"] = c.Lang 593 | } 594 | if c.HintText != "" { 595 | req.Params["textinstructions"] = c.HintText 596 | } 597 | if c.HintImageBase64 != "" { 598 | req.Params["imginstructions"] = c.HintImageBase64 599 | } 600 | if c.HintImageFile != "" { 601 | req.Files["imginstructions"] = c.HintImageFile 602 | } 603 | 604 | return req 605 | } 606 | 607 | func (c *Capy) ToRequest() Request { 608 | req := Request{ 609 | Params: map[string]string{"method": "capy"}, 610 | } 611 | if c.SiteKey != "" { 612 | req.Params["captchakey"] = c.SiteKey 613 | } 614 | if c.Url != "" { 615 | req.Params["pageurl"] = c.Url 616 | } 617 | if c.ApiServer != "" { 618 | req.Params["api_server"] = c.ApiServer 619 | } 620 | 621 | return req 622 | } 623 | 624 | func (c *Coordinates) ToRequest() Request { 625 | req := Request{ 626 | Params: map[string]string{"coordinatescaptcha": "1"}, 627 | Files: map[string]string{}, 628 | } 629 | if c.File != "" { 630 | req.Files["file"] = c.File 631 | } 632 | if c.Base64 != "" { 633 | req.Params["body"] = c.Base64 634 | } 635 | if c.Lang != "" { 636 | req.Params["lang"] = c.Lang 637 | } 638 | if c.HintText != "" { 639 | req.Params["textinstructions"] = c.HintText 640 | } 641 | if c.HintImageBase64 != "" { 642 | req.Params["imginstructions"] = c.HintImageBase64 643 | } 644 | if c.HintImageFile != "" { 645 | req.Files["imginstructions"] = c.HintImageFile 646 | } 647 | 648 | return req 649 | } 650 | 651 | func (c *FunCaptcha) ToRequest() Request { 652 | req := Request{ 653 | Params: map[string]string{"method": "funcaptcha"}, 654 | } 655 | if c.SiteKey != "" { 656 | req.Params["publickey"] = c.SiteKey 657 | } 658 | if c.Url != "" { 659 | req.Params["pageurl"] = c.Url 660 | } 661 | if c.Surl != "" { 662 | req.Params["surl"] = c.Surl 663 | } 664 | if c.UserAgent != "" { 665 | req.Params["userAgent"] = c.UserAgent 666 | } 667 | if c.Data != nil { 668 | for key, value := range c.Data { 669 | param := "data[" + key + "]" 670 | req.Params[param] = value 671 | } 672 | } 673 | 674 | return req 675 | } 676 | 677 | func (c *GeeTest) ToRequest() Request { 678 | req := Request{ 679 | Params: map[string]string{"method": "geetest"}, 680 | } 681 | if c.GT != "" { 682 | req.Params["gt"] = c.GT 683 | } 684 | if c.Challenge != "" { 685 | req.Params["challenge"] = c.Challenge 686 | } 687 | if c.Url != "" { 688 | req.Params["pageurl"] = c.Url 689 | } 690 | if c.ApiServer != "" { 691 | req.Params["api_server"] = c.ApiServer 692 | } 693 | 694 | return req 695 | } 696 | 697 | func (c *Grid) ToRequest() Request { 698 | req := Request{ 699 | Params: map[string]string{}, 700 | Files: map[string]string{}, 701 | } 702 | if c.File != "" { 703 | req.Files["file"] = c.File 704 | } 705 | if c.Base64 != "" { 706 | req.Params["body"] = c.Base64 707 | } 708 | if c.Rows != 0 { 709 | req.Params["recaptcharows"] = strconv.FormatInt(int64(c.Rows), 10) 710 | } 711 | if c.Cols != 0 { 712 | req.Params["recaptchacols"] = strconv.FormatInt(int64(c.Cols), 10) 713 | } 714 | if c.PreviousId != 0 { 715 | req.Params["previousID"] = strconv.FormatInt(int64(c.PreviousId), 10) 716 | } 717 | if c.CanSkip { 718 | req.Params["can_no_answer"] = "1" 719 | } 720 | if c.Lang != "" { 721 | req.Params["lang"] = c.Lang 722 | } 723 | if c.HintText != "" { 724 | req.Params["textinstructions"] = c.HintText 725 | } 726 | if c.HintImageBase64 != "" { 727 | req.Params["imginstructions"] = c.HintImageBase64 728 | } 729 | if c.HintImageFile != "" { 730 | req.Files["imginstructions"] = c.HintImageFile 731 | } 732 | 733 | return req 734 | } 735 | 736 | func (c *HCaptcha) ToRequest() Request { 737 | req := Request{ 738 | Params: map[string]string{"method": "hcaptcha"}, 739 | } 740 | if c.SiteKey != "" { 741 | req.Params["sitekey"] = c.SiteKey 742 | } 743 | if c.Url != "" { 744 | req.Params["pageurl"] = c.Url 745 | } 746 | 747 | return req 748 | } 749 | 750 | func (c *KeyCaptcha) ToRequest() Request { 751 | req := Request{ 752 | Params: map[string]string{"method": "keycaptcha"}, 753 | } 754 | if c.UserId != 0 { 755 | req.Params["s_s_c_user_id"] = strconv.FormatInt(int64(c.UserId), 10) 756 | } 757 | if c.SessionId != "" { 758 | req.Params["s_s_c_session_id"] = c.SessionId 759 | } 760 | if c.WebServerSign != "" { 761 | req.Params["s_s_c_web_server_sign"] = c.WebServerSign 762 | } 763 | if c.WebServerSign2 != "" { 764 | req.Params["s_s_c_web_server_sign2"] = c.WebServerSign2 765 | } 766 | if c.Url != "" { 767 | req.Params["pageurl"] = c.Url 768 | } 769 | 770 | return req 771 | } 772 | 773 | func (c *ReCaptcha) ToRequest() Request { 774 | req := Request{ 775 | Params: map[string]string{"method": "userrecaptcha"}, 776 | } 777 | if c.SiteKey != "" { 778 | req.Params["googlekey"] = c.SiteKey 779 | } 780 | if c.Url != "" { 781 | req.Params["pageurl"] = c.Url 782 | } 783 | if c.Invisible { 784 | req.Params["invisible"] = "1" 785 | } 786 | if c.Enterprise { 787 | req.Params["enterprise"] = "1" 788 | } 789 | if c.Version != "" { 790 | req.Params["version"] = c.Version 791 | } 792 | if c.Action != "" { 793 | req.Params["action"] = c.Action 794 | } 795 | if c.DataS != "" { 796 | req.Params["data-s"] = c.DataS 797 | } 798 | if c.Score != 0 { 799 | req.Params["min_score"] = strconv.FormatFloat(c.Score, 'f', -1, 64) 800 | } 801 | 802 | return req 803 | } 804 | 805 | func (c *Rotate) ToRequest() Request { 806 | req := Request{ 807 | Params: map[string]string{"method": "rotatecaptcha"}, 808 | Files: map[string]string{}, 809 | } 810 | if c.File != "" { 811 | req.Files["file"] = c.File 812 | } 813 | if c.Files != nil { 814 | for i := 0; i < len(c.Files); i++ { 815 | name := "file_" + strconv.FormatInt(int64(i)+1, 10) 816 | req.Files[name] = c.Files[i] 817 | } 818 | } 819 | if c.Angle != 0 { 820 | req.Params["angle"] = strconv.FormatInt(int64(c.Angle), 10) 821 | } 822 | if c.Lang != "" { 823 | req.Params["lang"] = c.Lang 824 | } 825 | if c.HintText != "" { 826 | req.Params["textinstructions"] = c.HintText 827 | } 828 | if c.HintImageBase64 != "" { 829 | req.Params["imginstructions"] = c.HintImageBase64 830 | } 831 | if c.HintImageFile != "" { 832 | req.Files["imginstructions"] = c.HintImageFile 833 | } 834 | if c.Base64 != "" { 835 | req.Params["body"] = c.Base64 836 | } 837 | return req 838 | } 839 | 840 | func (c *Text) ToRequest() Request { 841 | req := Request{ 842 | Params: map[string]string{"method": "post"}, 843 | } 844 | if c.Text != "" { 845 | req.Params["textcaptcha"] = c.Text 846 | } 847 | if c.Lang != "" { 848 | req.Params["lang"] = c.Lang 849 | } 850 | 851 | return req 852 | } 853 | 854 | func (c *AmazonWAF) ToRequest() Request { 855 | req := Request{ 856 | Params: map[string]string{"method": "amazon_waf"}, 857 | } 858 | 859 | if c.Iv != "" { 860 | req.Params["iv"] = c.Iv 861 | } 862 | 863 | if c.SiteKey != "" { 864 | req.Params["sitekey"] = c.SiteKey 865 | } 866 | 867 | if c.Url != "" { 868 | req.Params["pageurl"] = c.Url 869 | } 870 | 871 | if c.Context != "" { 872 | req.Params["context"] = c.Context 873 | } 874 | 875 | if c.ChallengeScript != "" { 876 | req.Params["challenge_script"] = c.ChallengeScript 877 | } 878 | 879 | if c.CaptchaScript != "" { 880 | req.Params["captcha_script"] = c.CaptchaScript 881 | } 882 | 883 | return req 884 | } 885 | 886 | func (c *GeeTestV4) ToRequest() Request { 887 | req := Request{ 888 | Params: map[string]string{"method": "geetest_v4"}, 889 | } 890 | if c.CaptchaId != "" { 891 | req.Params["captcha_id"] = c.CaptchaId 892 | } 893 | if c.Url != "" { 894 | req.Params["pageurl"] = c.Url 895 | } 896 | 897 | return req 898 | } 899 | 900 | func (c *Lemin) ToRequest() Request { 901 | req := Request{ 902 | Params: map[string]string{"method": "lemin"}, 903 | } 904 | 905 | if c.CaptchaId != "" { 906 | req.Params["captcha_id"] = c.CaptchaId 907 | } 908 | 909 | if c.DivId != "" { 910 | req.Params["div_id"] = c.DivId 911 | } else { 912 | req.Params["div_id"] = "lemin-cropped-captcha" 913 | } 914 | 915 | if c.Url != "" { 916 | req.Params["pageurl"] = c.Url 917 | } 918 | 919 | if c.ApiServer != "" { 920 | req.Params["api_server"] = c.ApiServer 921 | } 922 | return req 923 | } 924 | 925 | func (c *CloudflareTurnstile) ToRequest() Request { 926 | req := Request{ 927 | Params: map[string]string{"method": "turnstile"}, 928 | } 929 | 930 | if c.SiteKey != "" { 931 | req.Params["sitekey"] = c.SiteKey 932 | } 933 | if c.Url != "" { 934 | req.Params["pageurl"] = c.Url 935 | } 936 | if c.Data != "" { 937 | req.Params["data"] = c.Data 938 | } 939 | if c.PageData != "" { 940 | req.Params["pagedata"] = c.PageData 941 | } 942 | if c.Action != "" { 943 | req.Params["action"] = c.Action 944 | } 945 | if c.UserAgent != "" { 946 | req.Params["userAgent"] = c.UserAgent 947 | } 948 | 949 | return req 950 | } 951 | 952 | func (c *CyberSiARA) ToRequest() Request { 953 | req := Request{ 954 | Params: map[string]string{"method": "cybersiara"}, 955 | } 956 | 957 | if c.MasterUrlId != "" { 958 | req.Params["master_url_id"] = c.MasterUrlId 959 | } 960 | if c.Url != "" { 961 | req.Params["pageurl"] = c.Url 962 | } 963 | if c.UserAgent != "" { 964 | req.Params["userAgent"] = c.UserAgent 965 | } 966 | 967 | return req 968 | } 969 | 970 | func (c *DataDome) ToRequest() Request { 971 | req := Request{ 972 | Params: map[string]string{"method": "datadome"}, 973 | } 974 | 975 | if c.CaptchaUrl != "" { 976 | req.Params["captcha_url"] = c.CaptchaUrl 977 | } 978 | if c.Url != "" { 979 | req.Params["pageurl"] = c.Url 980 | } 981 | if c.Proxytype != "" { 982 | req.Params["proxytype"] = c.Proxytype 983 | } 984 | if c.Proxy != "" { 985 | req.Params["proxy"] = c.Proxy 986 | } 987 | if c.UserAgent != "" { 988 | req.Params["userAgent"] = c.UserAgent 989 | } 990 | 991 | return req 992 | } 993 | 994 | func (c *MTCaptcha) ToRequest() Request { 995 | req := Request{ 996 | Params: map[string]string{"method": "mt_captcha"}, 997 | } 998 | 999 | if c.SiteKey != "" { 1000 | req.Params["sitekey"] = c.SiteKey 1001 | } 1002 | if c.Url != "" { 1003 | req.Params["pageurl"] = c.Url 1004 | } 1005 | 1006 | return req 1007 | } 1008 | 1009 | func (c *Yandex) ToRequest() Request { 1010 | req := Request{ 1011 | Params: map[string]string{"method": "yandex"}, 1012 | } 1013 | 1014 | if c.SiteKey != "" { 1015 | req.Params["sitekey"] = c.SiteKey 1016 | } 1017 | if c.Url != "" { 1018 | req.Params["pageurl"] = c.Url 1019 | } 1020 | 1021 | return req 1022 | } 1023 | 1024 | func (c *Friendly) ToRequest() Request { 1025 | req := Request{ 1026 | Params: map[string]string{"method": "friendly_captcha"}, 1027 | } 1028 | 1029 | if c.SiteKey != "" { 1030 | req.Params["sitekey"] = c.SiteKey 1031 | } 1032 | if c.Url != "" { 1033 | req.Params["pageurl"] = c.Url 1034 | } 1035 | 1036 | return req 1037 | } 1038 | 1039 | func (c *Tencent) ToRequest() Request { 1040 | req := Request{ 1041 | Params: map[string]string{"method": "tencent"}, 1042 | } 1043 | if c.AppId != "" { 1044 | req.Params["app_id"] = c.AppId 1045 | } 1046 | if c.Url != "" { 1047 | req.Params["pageurl"] = c.Url 1048 | } 1049 | 1050 | return req 1051 | } 1052 | 1053 | func (c *AtbCAPTCHA) ToRequest() Request { 1054 | req := Request{ 1055 | Params: map[string]string{"method": "atb_captcha"}, 1056 | } 1057 | if c.AppId != "" { 1058 | req.Params["app_id"] = c.AppId 1059 | } 1060 | if c.Url != "" { 1061 | req.Params["pageurl"] = c.Url 1062 | } 1063 | if c.ApiServer != "" { 1064 | req.Params["api_server"] = c.ApiServer 1065 | } 1066 | 1067 | return req 1068 | } 1069 | 1070 | func (c *CutCaptcha) ToRequest() Request { 1071 | req := Request{ 1072 | Params: map[string]string{"method": "cutcaptcha"}, 1073 | } 1074 | if c.MiseryKey != "" { 1075 | req.Params["misery_key"] = c.MiseryKey 1076 | } 1077 | if c.Url != "" { 1078 | req.Params["pageurl"] = c.Url 1079 | } 1080 | if c.DataApiKey != "" { 1081 | req.Params["api_key"] = c.DataApiKey 1082 | } 1083 | 1084 | return req 1085 | } 1086 | 1087 | func (c *Audio) ToRequest() Request { 1088 | req := Request{ 1089 | Params: map[string]string{"method": "audio"}, 1090 | } 1091 | if c.Base64 != "" { 1092 | req.Params["body"] = c.Base64 1093 | } 1094 | if c.Lang != "" { 1095 | req.Params["lang"] = c.Lang 1096 | } 1097 | 1098 | return req 1099 | } 1100 | -------------------------------------------------------------------------------- /examples/AmazonWAFExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | amazonWafCaptcha := api2captcha.AmazonWAF{ 13 | SiteKey: "AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AF5H1K/siwSLK7RfstKtN5bAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglg", 14 | Url: "https://non-existent-example.execute-api.us-east-1.amazonaws.com", 15 | Iv: "test_iv", 16 | Context: "test_context", 17 | } 18 | 19 | req := amazonWafCaptcha.ToRequest() 20 | 21 | token, captchaId, err := client.Solve(req) 22 | 23 | fmt.Println("token ::: " + token) 24 | fmt.Println("captchaId ::: " + captchaId) 25 | fmt.Print("error ::: ") 26 | fmt.Println(err) 27 | } 28 | -------------------------------------------------------------------------------- /examples/AtbCAPTCHAExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | atbCaptcha := api2captcha.AtbCAPTCHA{ 13 | AppId: "af23e041b22d000a11e22a230fa8991c", 14 | Url: "https://www.playzone.vip/", 15 | ApiServer: "https://cap.aisecurius.com", 16 | } 17 | 18 | req := atbCaptcha.ToRequest() 19 | 20 | token, captchaId, err := client.Solve(req) 21 | 22 | fmt.Println("token ::: " + token) 23 | fmt.Println("captchaId ::: " + captchaId) 24 | fmt.Print("error ::: ") 25 | fmt.Println(err) 26 | } 27 | -------------------------------------------------------------------------------- /examples/AudioExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | api2captcha "github.com/2captcha/2captcha-go" 7 | helper "github.com/2captcha/2captcha-go/examples/internal" 8 | "os" 9 | ) 10 | 11 | func main() { 12 | client := api2captcha.NewClient(os.Args[1]) 13 | 14 | assetsDir := helper.GetAssetsDir(os.Args[0]) 15 | 16 | fileName := assetsDir + "/" + "audio-en.mp3" 17 | 18 | bs := helper.ReadFile2BiteSlice(fileName) 19 | 20 | if bs == nil { 21 | return 22 | } 23 | 24 | fileBase64Str := base64.StdEncoding.EncodeToString(bs) 25 | 26 | audio := api2captcha.Audio{ 27 | Base64: fileBase64Str, 28 | Lang: "en", 29 | } 30 | 31 | req := audio.ToRequest() 32 | 33 | token, captchaId, err := client.Solve(req) 34 | 35 | fmt.Println("token ::: " + token) 36 | fmt.Println("captchaId ::: " + captchaId) 37 | fmt.Print("error ::: ") 38 | fmt.Println(err) 39 | } 40 | -------------------------------------------------------------------------------- /examples/CanvasExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | helper "github.com/2captcha/2captcha-go/examples/internal" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | client := api2captcha.NewClient(os.Args[1]) 12 | 13 | assetsDir := helper.GetAssetsDir(os.Args[0]) 14 | fileName := assetsDir + "/" + "canvas.jpg" 15 | 16 | canvasCaptcha := api2captcha.Canvas{ 17 | File: fileName, 18 | HintText: "Draw around apple", 19 | } 20 | 21 | req := canvasCaptcha.ToRequest() 22 | 23 | token, captchaId, err := client.Solve(req) 24 | 25 | fmt.Println("token ::: " + token) 26 | fmt.Println("captchaId ::: " + captchaId) 27 | fmt.Print("error ::: ") 28 | fmt.Println(err) 29 | } 30 | -------------------------------------------------------------------------------- /examples/CapyExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | capy := api2captcha.Capy{ 13 | SiteKey: "PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v", 14 | Url: "https://www.mysite.com/captcha/", 15 | ApiServer: "https://jp.api.capy.me/", 16 | } 17 | 18 | req := capy.ToRequest() 19 | 20 | token, captchaId, err := client.Solve(req) 21 | 22 | fmt.Println("token ::: " + token) 23 | fmt.Println("captchaId ::: " + captchaId) 24 | fmt.Print("error ::: ") 25 | fmt.Println(err) 26 | } 27 | -------------------------------------------------------------------------------- /examples/CloudflareTurnstileExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | cloudflareTurnstile := api2captcha.CloudflareTurnstile{ 13 | SiteKey: "0x4AAAAAAAChNiVJM_WtShFf", 14 | Url: "https://ace.fusionist.io", 15 | } 16 | 17 | req := cloudflareTurnstile.ToRequest() 18 | 19 | token, captchaId, err := client.Solve(req) 20 | 21 | fmt.Println("token ::: " + token) 22 | fmt.Println("captchaId ::: " + captchaId) 23 | fmt.Print("error ::: ") 24 | fmt.Println(err) 25 | } 26 | -------------------------------------------------------------------------------- /examples/CoordinatesExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | helper "github.com/2captcha/2captcha-go/examples/internal" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | client := api2captcha.NewClient(os.Args[1]) 12 | 13 | assetsDir := helper.GetAssetsDir(os.Args[0]) 14 | fileName := assetsDir + "/" + "grid.jpg" 15 | 16 | coordinates := api2captcha.Coordinates{ 17 | File: fileName, 18 | } 19 | 20 | req := coordinates.ToRequest() 21 | 22 | token, captchaId, err := client.Solve(req) 23 | 24 | fmt.Println("token ::: " + token) 25 | fmt.Println("captchaId ::: " + captchaId) 26 | fmt.Print("error ::: ") 27 | fmt.Println(err) 28 | } 29 | -------------------------------------------------------------------------------- /examples/CutCaptchaExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | cutCaptcha := api2captcha.CutCaptcha{ 13 | MiseryKey: "a1488b66da00bf332a1488993a5443c79047e752", 14 | Url: "https://filecrypt.co/Container/237D4D0995.html", 15 | DataApiKey: "SAb83IIB", 16 | } 17 | 18 | req := cutCaptcha.ToRequest() 19 | 20 | token, captchaId, err := client.Solve(req) 21 | 22 | fmt.Println("token ::: " + token) 23 | fmt.Println("captchaId ::: " + captchaId) 24 | fmt.Print("error ::: ") 25 | fmt.Println(err) 26 | } 27 | -------------------------------------------------------------------------------- /examples/CyberSiARAExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | cyberSiARA := api2captcha.CyberSiARA{ 13 | MasterUrlId: "tpjOCKjjpdzv3d8Ub2E9COEWKt1vl1Mv", 14 | Url: "https://demo.mycybersiara.com/", 15 | UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36\"", 16 | } 17 | 18 | req := cyberSiARA.ToRequest() 19 | 20 | token, captchaId, err := client.Solve(req) 21 | 22 | fmt.Println("token ::: " + token) 23 | fmt.Println("captchaId ::: " + captchaId) 24 | fmt.Print("error ::: ") 25 | fmt.Println(err) 26 | } 27 | -------------------------------------------------------------------------------- /examples/DataDomeExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | dataDome := api2captcha.DataDome{ 13 | CaptchaUrl: "https://geo.captcha-delivery.com/captcha/?initialCid=AHrlqAAA...P~XFrBVptk&t=fe&referer=https%3A%2F%2Fhexample.com&s=45239&e=c538be..c510a00ea", 14 | Url: "https://example.com/", 15 | Proxy: "username:password@1.2.3.4:5678", 16 | Proxytype: "http", 17 | UserAgent: "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Mobile Safari/537.3", 18 | } 19 | 20 | req := dataDome.ToRequest() 21 | 22 | token, captchaId, err := client.Solve(req) 23 | 24 | fmt.Println("token ::: " + token) 25 | fmt.Println("captchaId ::: " + captchaId) 26 | fmt.Print("error ::: ") 27 | fmt.Println(err) 28 | } 29 | -------------------------------------------------------------------------------- /examples/FriendlyCaptchaExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | friendlyCaptcha := api2captcha.Friendly{ 13 | SiteKey: "FCMST5VUMCBOCGQ9", 14 | Url: "https://geizhals.de/455973138?fsean=5901747021356", 15 | } 16 | 17 | request := friendlyCaptcha.ToRequest() 18 | 19 | token, captchaId, err := client.Solve(request) 20 | 21 | fmt.Println("token ::: " + token) 22 | fmt.Println("captchaId ::: " + captchaId) 23 | fmt.Print("error ::: ") 24 | fmt.Println(err) 25 | } 26 | -------------------------------------------------------------------------------- /examples/FriendlyExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | friendly := api2captcha.Friendly{ 13 | SiteKey: "FCMST5VUMCBOCGQ9", 14 | Url: "https://geizhals.de/455973138?fsean=5901747021356", 15 | } 16 | 17 | req := friendly.ToRequest() 18 | 19 | token, captchaId, err := client.Solve(req) 20 | 21 | fmt.Println("token ::: " + token) 22 | fmt.Println("captchaId ::: " + captchaId) 23 | fmt.Print("error ::: ") 24 | fmt.Println(err) 25 | } 26 | -------------------------------------------------------------------------------- /examples/FunCaptchaExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | funCaptcha := api2captcha.FunCaptcha{ 13 | SiteKey: "69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC", 14 | Url: "https://mysite.com/page/with/funcaptcha", 15 | } 16 | 17 | req := funCaptcha.ToRequest() 18 | 19 | token, captchaId, err := client.Solve(req) 20 | 21 | fmt.Println("token ::: " + token) 22 | fmt.Println("captchaId ::: " + captchaId) 23 | fmt.Print("error ::: ") 24 | fmt.Println(err) 25 | } 26 | -------------------------------------------------------------------------------- /examples/GeeTestExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | geeTest := api2captcha.GeeTest{ 13 | GT: "f2ae6cadcf7886856696502e1d55e00c", 14 | Url: "https://www.mysite.com/captcha/", 15 | ApiServer: "api-na.geetest.com", 16 | Challenge: "12345678abc90123d45678ef90123a456b", 17 | } 18 | 19 | req := geeTest.ToRequest() 20 | 21 | token, captchaId, err := client.Solve(req) 22 | 23 | fmt.Println("token ::: " + token) 24 | fmt.Println("captchaId ::: " + captchaId) 25 | fmt.Print("error ::: ") 26 | fmt.Println(err) 27 | } 28 | -------------------------------------------------------------------------------- /examples/GeeTestV4Example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | geeTestV4 := api2captcha.GeeTestV4{ 13 | CaptchaId: "72bf15796d0b69c43867452fea615052", 14 | Url: "https://mysite.com/captcha.html", 15 | Challenge: "12345678abc90123d45678ef90123a456b", 16 | ApiServer: "api-na.geetest.com", 17 | } 18 | 19 | req := geeTestV4.ToRequest() 20 | 21 | token, captchaId, err := client.Solve(req) 22 | 23 | fmt.Println("token ::: " + token) 24 | fmt.Println("captchaId ::: " + captchaId) 25 | fmt.Print("error ::: ") 26 | fmt.Println(err) 27 | } 28 | -------------------------------------------------------------------------------- /examples/GridExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | helper "github.com/2captcha/2captcha-go/examples/internal" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | client := api2captcha.NewClient(os.Args[1]) 12 | 13 | assetsDir := helper.GetAssetsDir(os.Args[0]) 14 | fileName := assetsDir + "/" + "grid.jpg" 15 | 16 | grid := api2captcha.Grid{ 17 | File: fileName, 18 | } 19 | 20 | req := grid.ToRequest() 21 | 22 | token, captchaId, err := client.Solve(req) 23 | 24 | fmt.Println("token ::: " + token) 25 | fmt.Println("captchaId ::: " + captchaId) 26 | fmt.Print("error ::: ") 27 | fmt.Println(err) 28 | } 29 | -------------------------------------------------------------------------------- /examples/KeyCaptchaExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | keyCaptcha := api2captcha.KeyCaptcha{ 13 | UserId: 10, 14 | SessionId: "493e52c37c10c2bcdf4a00cbc9ccd1e8", 15 | WebServerSign: "9006dc725760858e4c0715b835472f22", 16 | WebServerSign2: "2ca3abe86d90c6142d5571db98af6714", 17 | Url: "https://www.keycaptcha.ru/demo-magnetic/", 18 | } 19 | 20 | req := keyCaptcha.ToRequest() 21 | 22 | token, captchaId, err := client.Solve(req) 23 | 24 | fmt.Println("token ::: " + token) 25 | fmt.Println("captchaId ::: " + captchaId) 26 | fmt.Print("error ::: ") 27 | fmt.Println(err) 28 | } 29 | -------------------------------------------------------------------------------- /examples/LeminExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | lemin := api2captcha.Lemin{ 13 | CaptchaId: "CROPPED_d3d4d56_73ca4008925b4f83a8bed59c2dd0df6d", 14 | Url: "https://www.site.com/page/", 15 | ApiServer: "api.leminnow.com", 16 | } 17 | 18 | req := lemin.ToRequest() 19 | 20 | token, captchaId, err := client.Solve(req) 21 | 22 | fmt.Println("token ::: " + token) 23 | fmt.Println("captchaId ::: " + captchaId) 24 | fmt.Print("error ::: ") 25 | fmt.Println(err) 26 | } 27 | -------------------------------------------------------------------------------- /examples/MTCaptchaExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | mtCaptcha := api2captcha.MTCaptcha{ 13 | SiteKey: "MTPublic-KzqLY1cKH", 14 | Url: "https://2captcha.com/demo/mtcaptcha", 15 | } 16 | 17 | req := mtCaptcha.ToRequest() 18 | 19 | token, captchaId, err := client.Solve(req) 20 | 21 | fmt.Println("token ::: " + token) 22 | fmt.Println("captchaId ::: " + captchaId) 23 | fmt.Print("error ::: ") 24 | fmt.Println(err) 25 | } 26 | -------------------------------------------------------------------------------- /examples/NormalExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | helper "github.com/2captcha/2captcha-go/examples/internal" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | client := api2captcha.NewClient(os.Args[1]) 12 | 13 | assetsDir := helper.GetAssetsDir(os.Args[0]) 14 | fileName := assetsDir + "/" + "normal.jpg" 15 | 16 | normal := api2captcha.Normal{ 17 | File: fileName, 18 | } 19 | 20 | req := normal.ToRequest() 21 | 22 | token, captchaId, err := client.Solve(req) 23 | 24 | fmt.Println("token ::: " + token) 25 | fmt.Println("captchaId ::: " + captchaId) 26 | fmt.Print("error ::: ") 27 | fmt.Println(err) 28 | } 29 | -------------------------------------------------------------------------------- /examples/ReCaptchaExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | reCaptcha := api2captcha.ReCaptcha{ 13 | SiteKey: "6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-", 14 | Url: "ttps://mysite.com/page/with/recaptcha", 15 | } 16 | 17 | req := reCaptcha.ToRequest() 18 | 19 | token, captchaId, err := client.Solve(req) 20 | 21 | fmt.Println("token ::: " + token) 22 | fmt.Println("captchaId ::: " + captchaId) 23 | fmt.Print("error ::: ") 24 | fmt.Println(err) 25 | } 26 | -------------------------------------------------------------------------------- /examples/RotateExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | api2captcha "github.com/2captcha/2captcha-go" 7 | helper "github.com/2captcha/2captcha-go/examples/internal" 8 | "os" 9 | ) 10 | 11 | func main() { 12 | client := api2captcha.NewClient(os.Args[1]) 13 | 14 | assetsDir := helper.GetAssetsDir(os.Args[0]) 15 | 16 | fileName := assetsDir + "/" + "rotate.jpg" 17 | 18 | bs := helper.ReadFile2BiteSlice(fileName) 19 | 20 | if bs == nil { 21 | return 22 | } 23 | 24 | fileBase64Str := base64.StdEncoding.EncodeToString(bs) 25 | 26 | rotate := api2captcha.Rotate{ 27 | Base64: fileBase64Str, 28 | } 29 | 30 | req := rotate.ToRequest() 31 | 32 | token, captchaId, err := client.Solve(req) 33 | 34 | fmt.Println("token ::: " + token) 35 | fmt.Println("captchaId ::: " + captchaId) 36 | fmt.Print("error ::: ") 37 | fmt.Println(err) 38 | } 39 | -------------------------------------------------------------------------------- /examples/TencentExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | tencentCaptcha := api2captcha.Tencent{ 13 | AppId: "2092215077", 14 | Url: "http://lcec.lclog.cn/cargo/NewCargotracking?blno=BANR01XMHB0004&selectstate=BLNO", 15 | } 16 | 17 | req := tencentCaptcha.ToRequest() 18 | 19 | token, captchaId, err := client.Solve(req) 20 | 21 | fmt.Println("token ::: " + token) 22 | fmt.Println("captchaId ::: " + captchaId) 23 | fmt.Print("error ::: ") 24 | fmt.Println(err) 25 | } 26 | -------------------------------------------------------------------------------- /examples/TextExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | text := api2captcha.Text{ 13 | Text: "If tomorrow is Saturday, what day is today?", 14 | } 15 | 16 | req := text.ToRequest() 17 | 18 | token, captchaId, err := client.Solve(req) 19 | 20 | fmt.Println("token ::: " + token) 21 | fmt.Println("captchaId ::: " + captchaId) 22 | fmt.Print("error ::: ") 23 | fmt.Println(err) 24 | } 25 | -------------------------------------------------------------------------------- /examples/YandexExample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | api2captcha "github.com/2captcha/2captcha-go" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | client := api2captcha.NewClient(os.Args[1]) 11 | 12 | yandex := api2captcha.Yandex{ 13 | SiteKey: "Y5Lh0tiycconMJGsFd3EbbuNKSp1yaZESUOIHfeV", 14 | Url: "https://rutube.ru", 15 | } 16 | 17 | req := yandex.ToRequest() 18 | 19 | token, captchaId, err := client.Solve(req) 20 | 21 | fmt.Println("token ::: " + token) 22 | fmt.Println("captchaId ::: " + captchaId) 23 | fmt.Print("error ::: ") 24 | fmt.Println(err) 25 | } 26 | -------------------------------------------------------------------------------- /examples/assets/audio-en.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2captcha/2captcha-go/da20509fedf9592b414601a2755bc4e41f0dc087/examples/assets/audio-en.mp3 -------------------------------------------------------------------------------- /examples/assets/canvas.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2captcha/2captcha-go/da20509fedf9592b414601a2755bc4e41f0dc087/examples/assets/canvas.jpg -------------------------------------------------------------------------------- /examples/assets/grid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2captcha/2captcha-go/da20509fedf9592b414601a2755bc4e41f0dc087/examples/assets/grid.jpg -------------------------------------------------------------------------------- /examples/assets/normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2captcha/2captcha-go/da20509fedf9592b414601a2755bc4e41f0dc087/examples/assets/normal.jpg -------------------------------------------------------------------------------- /examples/assets/rotate.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2captcha/2captcha-go/da20509fedf9592b414601a2755bc4e41f0dc087/examples/assets/rotate.jpg -------------------------------------------------------------------------------- /examples/internal/Helper.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "log" 8 | "os" 9 | "path/filepath" 10 | ) 11 | 12 | func GetAssetsDir(currentDir string) string { 13 | currentDir, err := filepath.Abs(filepath.Dir(currentDir)) 14 | assetsDir := currentDir + "/assets" 15 | 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | return assetsDir 20 | } 21 | 22 | func ReadFile2BiteSlice(fileName string) []byte { 23 | 24 | file, err := os.Open(fileName) 25 | if err != nil { 26 | fmt.Println(err) 27 | return nil 28 | } 29 | defer file.Close() 30 | 31 | stat, err := file.Stat() 32 | if err != nil { 33 | fmt.Println(err) 34 | return nil 35 | } 36 | 37 | bs := make([]byte, stat.Size()) 38 | _, err = bufio.NewReader(file).Read(bs) 39 | if err != nil && err != io.EOF { 40 | fmt.Println(err) 41 | return nil 42 | } 43 | return bs 44 | } 45 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/2captcha/2captcha-go 2 | 3 | go 1.22.4 4 | --------------------------------------------------------------------------------