solvecaptcha-ruby 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/CODE_OF_CONDUCT.md +43 -0
  3. data/CONTRIBUTING.md +72 -0
  4. data/Gemfile +14 -0
  5. data/LICENSE +21 -0
  6. data/README.md +640 -0
  7. data/RELEASING.md +16 -0
  8. data/Rakefile +12 -0
  9. data/api_solvecaptcha.gemspec +39 -0
  10. data/examples/amazon_waf_example.rb +7 -0
  11. data/examples/atb_captcha_example.rb +11 -0
  12. data/examples/audio_example.rb +10 -0
  13. data/examples/canvas_example.rb +7 -0
  14. data/examples/capy_example.rb +7 -0
  15. data/examples/clickcaptcha_example.rb +7 -0
  16. data/examples/cutcaptcha_example.rb +7 -0
  17. data/examples/cybersiara_example.rb +7 -0
  18. data/examples/datadome_example.rb +7 -0
  19. data/examples/friendlycaptcha_example.rb +7 -0
  20. data/examples/funcaptcha_example.rb +7 -0
  21. data/examples/geetest_example.rb +7 -0
  22. data/examples/geetest_v4_example.rb +7 -0
  23. data/examples/grid_captcha_example.rb +14 -0
  24. data/examples/hcaptcha_example.rb +10 -0
  25. data/examples/keycaptcha_example.rb +7 -0
  26. data/examples/lemin_example.rb +7 -0
  27. data/examples/media/example.mp3 +0 -0
  28. data/examples/media/normal_2.jpg +0 -0
  29. data/examples/media/recaptchaGrid4x4.jpg +0 -0
  30. data/examples/media/recaptchaGridImginstructions4x4.jpg +0 -0
  31. data/examples/mtcaptcha_example.rb +7 -0
  32. data/examples/normal_captcha_example.rb +15 -0
  33. data/examples/recaptcha_enterprise_example.rb +7 -0
  34. data/examples/recaptcha_v2_example.rb +10 -0
  35. data/examples/recaptcha_v3_example.rb +7 -0
  36. data/examples/rotate_example.rb +7 -0
  37. data/examples/tencent_example.rb +10 -0
  38. data/examples/turnstile_example.rb +7 -0
  39. data/examples/yandex_smart_example.rb +7 -0
  40. data/lib/api_solvecaptcha/api_solvecaptcha_exceptions.rb +25 -0
  41. data/lib/api_solvecaptcha/client.rb +166 -0
  42. data/lib/api_solvecaptcha/version.rb +5 -0
  43. data/lib/api_solvecaptcha.rb +13 -0
  44. metadata +93 -0
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/api_solvecaptcha/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "solvecaptcha-ruby"
7
+ spec.version = ApiSolveCaptcha::VERSION
8
+ spec.authors = ["solvecaptcha.com"]
9
+
10
+ spec.summary = "Solvercaptcha API wrapper for Ruby."
11
+ spec.description = "Ruby package for easy integration with the API of solvecaptcha captcha solving service to bypass recaptcha, funcaptcha, geetest and solve any other captchas."
12
+ spec.homepage = "https://solvecaptcha.com//"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = ">= 2.6.0"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/solvercaptcha/solvecaptcha-ruby"
18
+ spec.metadata["changelog_uri"] = "https://github.com/solvercaptcha/solvecaptcha-ruby/releases"
19
+ spec.metadata["github_repo"] = "ssh://github.com/solvercaptcha/solvecaptcha-ruby"
20
+ spec.metadata["bug_tracker_uri"] = "https://github.com/solvercaptcha/solvecaptcha-ruby/issues"
21
+ spec.metadata["keywords"] = "Solvercaptcha, captcha solver, captcha bypass, Ruby, automation, CAPTCHA API, CAPTCHA recognition, anti-captcha, reCAPTCHA, OCR, image recognition, human verification, bot protection, recaptcha"
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(__dir__) do
26
+ `git ls-files -z`.split("\x0").reject do |f|
27
+ (File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor])
28
+ end
29
+ end
30
+ spec.bindir = "bin"
31
+ spec.executables = spec.files.grep(%r{\Abin/}) { |f| File.basename(f) }
32
+ spec.require_paths = ["lib"]
33
+
34
+ # Uncomment to register a new dependency of your gem
35
+ # spec.add_dependency "example-gem", "~> 1.0"
36
+
37
+ # For more information and examples about making a new gem, check out our
38
+ # guide at: https://bundler.io/guides/creating_gem.html
39
+ end
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.amazon_waf({'sitekey': 'SITEKEY', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,11 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha.new("YOUR_API_KEY")
4
+
5
+ result = client.atb_captcha({
6
+ app_id: "197326679",
7
+ api_server: "api.atb_captcha.com",
8
+ pageurl: "https://mysite.com/page/with/atb_captcha"
9
+ })
10
+
11
+ puts "Result: #{result.inspect}"
@@ -0,0 +1,10 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha.new("YOUR_API_KEY")
4
+
5
+ result = client.audio({
6
+ audio: './media/example.mp3',
7
+ lang: "en"
8
+ })
9
+
10
+ puts "Result: #{result.inspect}"
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.canvas({'canvas': 'BASE64_CANVAS_IMAGE'})
6
+
7
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.capy({'sitekey': 'SITEKEY', 'pageurl': 'https://example.com', 'api_server': 'https://api.capy.me'})
6
+
7
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.clickcaptcha({'img': 'BASE64_IMAGE', 'coords': '120,50;140,70'})
6
+
7
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.cutcaptcha({'captchakey': 'CAPTCHAKEY', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.cybersiara({'siara_id': 'SIARA_ID', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.datadome({'captcha_url': 'https://example.com/captcha', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.friendlycaptcha({'sitekey': 'SITEKEY', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.funcaptcha({'publickey': 'PUBLICKEY', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.geetest({'gt': 'GT', 'challenge': 'CHALLENGE', 'api_server': 'https://api.geetest.com', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.geetest_v4({'captcha_id': 'CAPTCHA_ID', 'lot_number': 'LOT_NUMBER', 'payload': '{}', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,14 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha.new("YOUR_API_KEY")
4
+
5
+ result = client.grid({
6
+ image: './media/recaptchaGrid4x4.jpg',
7
+ rows: 4,
8
+ cols: 4,
9
+ lang: 'en',
10
+ hint_image: './media/recaptchaGridImginstructions4x4.jpg',
11
+ # hint_text: 'Select all squares with stairs'
12
+ })
13
+
14
+ puts "Result: #{result.inspect}"
@@ -0,0 +1,10 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.hcaptcha({
6
+ sitekey: 'SITEKEY',
7
+ pageurl: 'https://example.com'
8
+ })
9
+
10
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.keycaptcha({'s_s_c_user_id': 'USER_ID', 's_s_c_session_id': 'SESSION_ID', 's_s_c_web_server_sign': 'SIGN', 's_s_c_web_server_sign2': 'SIGN2', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.lemin({'captcha_id': 'CAPTCHA_ID', 'api_server': 'https://api.lemin.com', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
Binary file
Binary file
Binary file
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.mtcaptcha({'sitekey': 'SITEKEY', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,15 @@
1
+ require_relative "../lib/api_solvecaptcha"
2
+
3
+ client = ApiSolveCaptcha.new("YOUR_API_KEY")
4
+
5
+ image_path = File.join(__dir__, 'media', 'normal_2.jpg')
6
+
7
+ puts "Image path: #{image_path}"
8
+ puts "File exists: #{File.exist?(image_path)}"
9
+ puts "File size: #{File.size?(image_path).to_i} bytes"
10
+
11
+ result = client.normal({
12
+ image: image_path,
13
+ })
14
+
15
+ puts "Result: #{result.inspect}"
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.recaptcha_enterprise({'sitekey': 'SITEKEY', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,10 @@
1
+ require_relative "../lib/api_solvecaptcha"
2
+
3
+ client = ApiSolveCaptcha.new("6663f112abc465058b7a9b448d3a0f54")
4
+
5
+ result = client.recaptcha_v2({
6
+ googlekey: '6LfD3PIbAAAAAJs_eEHvoOl75_83eXSqpPSRFJ_u',
7
+ pageurl: 'https://solvecaptcha.com/demo/recaptcha-v2',
8
+ })
9
+
10
+ puts "Result: #{result.inspect}"
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.recaptcha_v3({'sitekey': 'SITEKEY', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.rotate({'body': 'BASE64_IMAGE'})
6
+
7
+ puts result
@@ -0,0 +1,10 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha.new("YOUR_API_KEY")
4
+
5
+ result = client.tencent({
6
+ app_id: "197326679",
7
+ pageurl: "https://mysite.com/page/with/tencent"
8
+ })
9
+
10
+ puts "Result: #{result.inspect}"
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.turnstile({'sitekey': 'SITEKEY', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,7 @@
1
+ require_relative '../lib/api_solvecaptcha'
2
+
3
+ client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
4
+
5
+ result = client.yandex_smart({'sitekey': 'SITEKEY', 'pageurl': 'https://example.com'})
6
+
7
+ puts result
@@ -0,0 +1,25 @@
1
+ module ApiSolveCaptcha
2
+ class ValidationException < StandardError
3
+ def initialize(message = 'Invalid parameters passed')
4
+ super(message)
5
+ end
6
+ end
7
+
8
+ class NetworkException < StandardError
9
+ def initialize(message = 'Network error occurred')
10
+ super(message)
11
+ end
12
+ end
13
+
14
+ class ApiException < StandardError
15
+ def initialize(message = 'API response error')
16
+ super(message)
17
+ end
18
+ end
19
+
20
+ class TimeoutException < StandardError
21
+ def initialize(message = 'Captcha solving timed out')
22
+ super(message)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,166 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'json'
4
+ require 'base64'
5
+ require 'open-uri'
6
+ require 'net/http/post/multipart'
7
+
8
+
9
+ module ApiSolveCaptcha
10
+ class Client
11
+ DEFAULT_DOMAIN = "api.solvecaptcha.com"
12
+ BASE_URL_FORMAT = "https://%s"
13
+
14
+ attr_accessor :domain, :callback, :default_timeout,
15
+ :soft_id, :recaptcha_timeout,
16
+ :polling_interval, :api_key
17
+
18
+ def initialize(api_key, callback = nil)
19
+ @api_key = api_key
20
+ @soft_id = nil
21
+ @callback = callback
22
+ @default_timeout = 120
23
+ @recaptcha_timeout = 600
24
+ @polling_interval = 5
25
+ @domain = DEFAULT_DOMAIN
26
+ end
27
+
28
+ def solve(method, return_id: false, **params)
29
+ params["method"] = method
30
+ params["key"] = @api_key
31
+ params["json"] = 1
32
+
33
+ params["pingback"] = @callback if @callback
34
+
35
+ complete_params = get_params(params)
36
+ captcha_id = send_request(complete_params)
37
+ return captcha_id if return_id
38
+
39
+ get_result(captcha_id)
40
+ end
41
+
42
+ def normal(params)
43
+ solve("post", **params)
44
+ end
45
+
46
+ def get_result(captcha_id)
47
+ uri = URI("#{base_url}/res.php?key=#{@api_key}&action=get&id=#{captcha_id}&json=1")
48
+ start_time = Time.now
49
+
50
+ loop do
51
+ response = make_request(uri)
52
+
53
+ if response.is_a?(Net::HTTPSuccess)
54
+ response_json = JSON.parse(response.body.strip)
55
+
56
+ case response_json["request"]
57
+ when "CAPCHA_NOT_READY"
58
+ sleep @polling_interval
59
+ when /[a-zA-Z0-9]+/
60
+ return response_json
61
+ else
62
+ raise "API Error: #{response_json["request"]}"
63
+ end
64
+ else
65
+ raise "Network Error: #{response.code}"
66
+ end
67
+
68
+ raise "Timeout" if Time.now - start_time > @default_timeout
69
+ end
70
+ end
71
+
72
+ def report(captcha_id, is_correct)
73
+ action = is_correct ? "reportgood" : "reportbad"
74
+ uri = URI("#{base_url}/res.php?key=#{@api_key}&action=#{action}&id=#{captcha_id}")
75
+ make_request(uri)
76
+ end
77
+
78
+ private
79
+
80
+ def base_url
81
+ BASE_URL_FORMAT % @domain
82
+ end
83
+
84
+ def get_params(params)
85
+ params["image"].nil? ? params : file_params(params)
86
+ end
87
+
88
+ def file_params(params)
89
+ image = params.delete("image")
90
+ hint_image = params.delete("hint_image")
91
+
92
+ image_content = if base64_encoded?(image)
93
+ image
94
+ else
95
+ Base64.strict_encode64(get_image_content(image))
96
+ end
97
+
98
+ hint_image_content = if hint_image
99
+ base64_encoded?(hint_image) ? hint_image : Base64.strict_encode64(get_image_content(hint_image))
100
+ end
101
+
102
+ result_params = {
103
+ "method" => "base64",
104
+ "body" => image_content,
105
+ "filename" => File.basename(image),
106
+ "ext" => File.extname(image).delete(".")
107
+ }
108
+
109
+ result_params["imginstructions"] = hint_image_content if hint_image_content
110
+ params.merge(result_params)
111
+ end
112
+
113
+ def get_image_content(image)
114
+ return download_image(image) if image.start_with?('http')
115
+ return File.binread(image) if File.file?(image)
116
+ image
117
+ end
118
+
119
+ def base64_encoded?(string)
120
+ string.is_a?(String) && string.match(/\A[A-Za-z0-9+\/=]+\z/) && (string.length % 4).zero?
121
+ end
122
+
123
+ def download_image(url)
124
+ response = URI.open(url)
125
+ if response.status[0] != '200'
126
+ raise StandardError, "File could not be downloaded from url: #{url}"
127
+ end
128
+ response.read
129
+ end
130
+
131
+
132
+ def send_request(params)
133
+ uri = URI("#{base_url}/in.php")
134
+
135
+ file_path = params.delete("image")
136
+ file = UploadIO.new(File.open(file_path), mime_type(file_path), File.basename(file_path))
137
+
138
+ form_data = params.merge("file" => file)
139
+
140
+ req = Net::HTTP::Post::Multipart.new(uri.path, form_data)
141
+
142
+ response = make_request(uri, req)
143
+
144
+ if response.is_a?(Net::HTTPSuccess)
145
+ parsed_response = JSON.parse(response.body.strip)
146
+
147
+ raise "API Error: #{parsed_response["request"]}" unless parsed_response["status"] == 1
148
+
149
+ parsed_response["request"]
150
+ else
151
+ raise "Network Error: #{response.code}"
152
+ end
153
+ end
154
+
155
+ def mime_type(file_path)
156
+ MIME::Types.type_for(file_path).first.to_s || "application/octet-stream"
157
+ end
158
+
159
+
160
+ def make_request(uri, req = nil)
161
+ Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
162
+ http.request(req || Net::HTTP::Get.new(uri))
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ApiSolveCaptcha
4
+ VERSION = "1.0.0"
5
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./api_solvecaptcha/api_solvecaptcha_exceptions"
4
+ require_relative "./api_solvecaptcha/client"
5
+ require_relative "./api_solvecaptcha/version"
6
+
7
+
8
+ module ApiSolveCaptcha
9
+ def self.new(*args)
10
+ Client.new(*args)
11
+ end
12
+ end
13
+
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: solvecaptcha-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - solvecaptcha.com
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-04-22 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby package for easy integration with the API of solvecaptcha captcha
14
+ solving service to bypass recaptcha, funcaptcha, geetest and solve any other captchas.
15
+ email:
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - CODE_OF_CONDUCT.md
21
+ - CONTRIBUTING.md
22
+ - Gemfile
23
+ - LICENSE
24
+ - README.md
25
+ - RELEASING.md
26
+ - Rakefile
27
+ - api_solvecaptcha.gemspec
28
+ - examples/amazon_waf_example.rb
29
+ - examples/atb_captcha_example.rb
30
+ - examples/audio_example.rb
31
+ - examples/canvas_example.rb
32
+ - examples/capy_example.rb
33
+ - examples/clickcaptcha_example.rb
34
+ - examples/cutcaptcha_example.rb
35
+ - examples/cybersiara_example.rb
36
+ - examples/datadome_example.rb
37
+ - examples/friendlycaptcha_example.rb
38
+ - examples/funcaptcha_example.rb
39
+ - examples/geetest_example.rb
40
+ - examples/geetest_v4_example.rb
41
+ - examples/grid_captcha_example.rb
42
+ - examples/hcaptcha_example.rb
43
+ - examples/keycaptcha_example.rb
44
+ - examples/lemin_example.rb
45
+ - examples/media/example.mp3
46
+ - examples/media/normal_2.jpg
47
+ - examples/media/recaptchaGrid4x4.jpg
48
+ - examples/media/recaptchaGridImginstructions4x4.jpg
49
+ - examples/mtcaptcha_example.rb
50
+ - examples/normal_captcha_example.rb
51
+ - examples/recaptcha_enterprise_example.rb
52
+ - examples/recaptcha_v2_example.rb
53
+ - examples/recaptcha_v3_example.rb
54
+ - examples/rotate_example.rb
55
+ - examples/tencent_example.rb
56
+ - examples/turnstile_example.rb
57
+ - examples/yandex_smart_example.rb
58
+ - lib/api_solvecaptcha.rb
59
+ - lib/api_solvecaptcha/api_solvecaptcha_exceptions.rb
60
+ - lib/api_solvecaptcha/client.rb
61
+ - lib/api_solvecaptcha/version.rb
62
+ homepage: https://solvecaptcha.com//
63
+ licenses:
64
+ - MIT
65
+ metadata:
66
+ homepage_uri: https://solvecaptcha.com//
67
+ source_code_uri: https://github.com/solvercaptcha/solvecaptcha-ruby
68
+ changelog_uri: https://github.com/solvercaptcha/solvecaptcha-ruby/releases
69
+ github_repo: ssh://github.com/solvercaptcha/solvecaptcha-ruby
70
+ bug_tracker_uri: https://github.com/solvercaptcha/solvecaptcha-ruby/issues
71
+ keywords: Solvercaptcha, captcha solver, captcha bypass, Ruby, automation, CAPTCHA
72
+ API, CAPTCHA recognition, anti-captcha, reCAPTCHA, OCR, image recognition, human
73
+ verification, bot protection, recaptcha
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 2.6.0
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubygems_version: 3.4.19
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: Solvercaptcha API wrapper for Ruby.
93
+ test_files: []