{"id":13463343,"url":"https://github.com/ambethia/recaptcha","last_synced_at":"2025-05-13T20:03:07.016Z","repository":{"id":391326,"uuid":"8970","full_name":"ambethia/recaptcha","owner":"ambethia","description":"ReCaptcha helpers for ruby apps","archived":false,"fork":false,"pushed_at":"2025-01-14T17:28:09.000Z","size":902,"stargazers_count":1998,"open_issues_count":50,"forks_count":442,"subscribers_count":27,"default_branch":"master","last_synced_at":"2025-05-06T01:35:34.704Z","etag":null,"topics":["captcha","rails","recaptcha","ruby","sinatra"],"latest_commit_sha":null,"homepage":"http://github.com/ambethia/recaptcha","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"dotansimha/angularjs-dropdown-multiselect","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ambethia.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2008-04-11T23:01:45.000Z","updated_at":"2025-05-05T06:59:38.000Z","dependencies_parsed_at":"2024-05-04T20:42:39.856Z","dependency_job_id":"e83fd6cc-5352-4543-b429-530debedddab","html_url":"https://github.com/ambethia/recaptcha","commit_stats":{"total_commits":538,"total_committers":161,"mean_commits":3.341614906832298,"dds":0.7026022304832713,"last_synced_commit":"8e5ccaedf230aa2af4da3a8a64e020f5c7d4fddd"},"previous_names":[],"tags_count":91,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ambethia%2Frecaptcha","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ambethia%2Frecaptcha/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ambethia%2Frecaptcha/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ambethia%2Frecaptcha/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ambethia","download_url":"https://codeload.github.com/ambethia/recaptcha/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252663503,"owners_count":21784783,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["captcha","rails","recaptcha","ruby","sinatra"],"created_at":"2024-07-31T13:00:51.495Z","updated_at":"2025-05-13T20:03:06.962Z","avatar_url":"https://github.com/ambethia.png","language":"Ruby","readme":"\n# reCAPTCHA\n[![Gem Version](https://badge.fury.io/rb/recaptcha.svg)](https://badge.fury.io/rb/recaptcha)\n\nAuthor:    Jason L Perry (http://ambethia.com)\u003cbr/\u003e\nCopyright: Copyright (c) 2007-2013 Jason L Perry\u003cbr/\u003e\nLicense:   [MIT](http://creativecommons.org/licenses/MIT/)\u003cbr/\u003e\nInfo:      https://github.com/ambethia/recaptcha\u003cbr/\u003e\nBugs:      https://github.com/ambethia/recaptcha/issues\u003cbr/\u003e\n\nThis gem provides helper methods for the [reCAPTCHA API](https://www.google.com/recaptcha). In your\nviews you can use the `recaptcha_tags` method to embed the needed javascript, and you can validate\nin your controllers with `verify_recaptcha` or `verify_recaptcha!`, which raises an error on\nfailure.\n\n\n# Table of Contents\n1. [Obtaining a key](#obtaining-a-key)\n2. [Rails Installation](#rails-installation)\n3. [Sinatra / Rack / Ruby Installation](#sinatra--rack--ruby-installation)\n4. [reCAPTCHA V2 API \u0026 Usage](#recaptcha-v2-api-and-usage)\n  - [`recaptcha_tags`](#recaptcha_tags)\n  - [`verify_recaptcha`](#verify_recaptcha)\n  - [`invisible_recaptcha_tags`](#invisible_recaptcha_tags)\n5. [reCAPTCHA V3 API \u0026 Usage](#recaptcha-v3-api-and-usage)\n  - [`recaptcha_v3`](#recaptcha_v3)\n  - [`verify_recaptcha` (use with v3)](#verify_recaptcha-use-with-v3)\n  - [`recaptcha_reply`](#recaptcha_reply)\n6. [I18n Support](#i18n-support)\n7. [Testing](#testing)\n8. [Alternative API Key Setup](#alternative-api-key-setup)\n\n## Obtaining a key\n\nGo to the [reCAPTCHA admin console](https://www.google.com/recaptcha/admin) to obtain a reCAPTCHA API key.\n\nThe reCAPTCHA type(s) that you choose for your key will determine which methods to use below.\n\n| reCAPTCHA type                               | Methods to use | Description |\n|----------------------------------------------|----------------|-------------|\n| v3                                           | [`recaptcha_v3`](#recaptcha_v3)                         | Verify requests with a [score](https://developers.google.com/recaptcha/docs/v3#score)\n| v2 Checkbox\u003cbr/\u003e(\"I'm not a robot\" Checkbox) | [`recaptcha_tags`](#recaptcha_tags)                     | Validate requests with the \"I'm not a robot\" checkbox |\n| v2 Invisible\u003cbr/\u003e(Invisible reCAPTCHA badge) | [`invisible_recaptcha_tags`](#invisible_recaptcha_tags) | Validate requests in the background |\n\nNote: You can _only_ use methods that match your key's type. You cannot use v2 methods with a v3\nkey or use `recaptcha_tags` with a v2 Invisible key, for example. Otherwise you will get an\nerror like \"Invalid key type\" or \"This site key is not enabled for the invisible captcha.\"\n\nNote: Enter `localhost` or `127.0.0.1` as the domain if using in development with `localhost:3000`.\n\n## Rails Installation\n\n**If you are having issues with Rails 7, Turbo, and Stimulus, make sure to check [this Wiki page](https://github.com/ambethia/recaptcha/wiki/Recaptcha-with-Turbo-and-Stimulus)!**\n\n```ruby\ngem \"recaptcha\"\n```\n\nYou can keep keys out of the code base with environment variables or with Rails [secrets](https://api.rubyonrails.org/classes/Rails/Application.html#method-i-secrets).\u003cbr/\u003e\n\nIn development, you can use the [dotenv](https://github.com/bkeepers/dotenv) gem. (Make sure to add it above `gem 'recaptcha'`.)\n\nSee [Alternative API key setup](#alternative-api-key-setup) for more ways to configure or override\nkeys. See also the\n[Configuration](https://www.rubydoc.info/github/ambethia/recaptcha/master/Recaptcha/Configuration)\ndocumentation.\n\n```shell\nexport RECAPTCHA_SITE_KEY   = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'\nexport RECAPTCHA_SECRET_KEY = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'\n```\n\nIf you have an Enterprise API key:\n\n```shell\nexport RECAPTCHA_ENTERPRISE            = 'true'\nexport RECAPTCHA_ENTERPRISE_API_KEY    = 'AIzvFyE3TU-g4K_Kozr9F1smEzZSGBVOfLKyupA'\nexport RECAPTCHA_ENTERPRISE_PROJECT_ID = 'my-project'\n```\n\n_note:_ you'll still have to provide `RECAPTCHA_SITE_KEY`, which will hold the value of your enterprise recaptcha key id. You will not need to provide a `RECAPTCHA_SECRET_KEY`, however.\n\n`RECAPTCHA_ENTERPRISE_API_KEY` is the enterprise key of your Google Cloud Project, which you can generate here: https://console.cloud.google.com/apis/credentials.\n\nAdd `recaptcha_tags` to the forms you want to protect:\n\n```erb\n\u003c%= form_for @foo do |f| %\u003e\n  # …\n  \u003c%= recaptcha_tags %\u003e\n  # …\n\u003c% end %\u003e\n```\n\nThen, add `verify_recaptcha` logic to each form action that you've protected:\n\n```ruby\n# app/controllers/users_controller.rb\n@user = User.new(params[:user].permit(:name))\nif verify_recaptcha(model: @user) \u0026\u0026 @user.save\n  redirect_to @user\nelse\n  render 'new'\nend\n```\nPlease note that this setup uses [`reCAPTCHA_v2`](#recaptcha-v2-api-and-usage). For a `recaptcha_v3` use, please refer to [`reCAPTCHA_v3 setup`](#examples).\n\n## Sinatra / Rack / Ruby installation\n\nSee [sinatra demo](/demo/sinatra) for details.\n\n - add `gem 'recaptcha'` to `Gemfile`\n - set env variables\n - `include Recaptcha::Adapters::ViewMethods` where you need `recaptcha_tags`\n - `include Recaptcha::Adapters::ControllerMethods` where you need `verify_recaptcha`\n\n\n## reCAPTCHA v2 API and Usage\n\n### `recaptcha_tags`\n\nUse this when your key's reCAPTCHA type is \"v2 Checkbox\".\n\nThe following options are available:\n\n| Option              | Description |\n|---------------------|-------------|\n| `:theme`            | Specify the theme to be used per the API. Available options: `dark` and `light`. (default: `light`) |\n| `:ajax`             | Render the dynamic AJAX captcha per the API. (default: `false`) |\n| `:site_key`         | Override site API key from configuration |\n| `:error`            | Override the error code returned from the reCAPTCHA API (default: `nil`) |\n| `:size`             | Specify a size (default: `nil`) |\n| `:nonce`            | Optional. Sets nonce attribute for script. Can be generated via `SecureRandom.base64(32)`. Use `content_security_policy_nonce` if you have `config.content_security_policy_nonce_generator` set in Rails. (default: `nil`) |\n| `:id`               | Specify an html id attribute (default: `nil`) |\n| `:callback`         | Optional. Name of success callback function, executed when the user submits a successful response |\n| `:expired_callback` | Optional. Name of expiration callback function, executed when the reCAPTCHA response expires and the user needs to re-verify. |\n| `:error_callback`   | Optional. Name of error callback function, executed when reCAPTCHA encounters an error (e.g. network connectivity) |\n| `:noscript`         | Include `\u003cnoscript\u003e` content (default: `true`)|\n\n[JavaScript resource (api.js) parameters](https://developers.google.com/recaptcha/docs/invisible#js_param):\n\n| Option              | Description |\n|---------------------|-------------|\n| `:onload`           | Optional. The name of your callback function to be executed once all the dependencies have loaded. (See [explicit rendering](https://developers.google.com/recaptcha/docs/display#explicit_render)) |\n| `:render`           | Optional. Whether to render the widget explicitly. Defaults to `onload`, which will render the widget in the first g-recaptcha tag it finds. (See [explicit rendering](https://developers.google.com/recaptcha/docs/display#explicit_render)) |\n| `:hl`               | Optional. Forces the widget to render in a specific language. Auto-detects the user's language if unspecified. (See [language codes](https://developers.google.com/recaptcha/docs/language)) |\n| `:script`           | Alias for `:external_script`. If you do not need to add a script tag by helper you can set the option to `false`. It's necessary when you add a script tag manualy (default: `true`). |\n| `:external_script`  | Set to `false` to avoid including a script tag for the external `api.js` resource. Useful when including multiple `recaptcha_tags` on the same page. |\n| `:script_async`     | Set to `false` to load the external `api.js` resource synchronously. (default: `true`) |\n| `:script_defer`     | Set to `true` to defer loading of external `api.js` until HTML documen has been parsed. (default: `true`) |\n\nAny unrecognized options will be added as attributes on the generated tag.\n\nYou can also override the html attributes for the sizes of the generated `textarea` and `iframe`\nelements, if CSS isn't your thing. Inspect the [source of `recaptcha_tags`](https://github.com/ambethia/recaptcha/blob/master/lib/recaptcha/helpers.rb)\nto see these options.\n\nNote that you cannot submit/verify the same response token more than once or you will get a\n`timeout-or-duplicate` error code. If you need reset the captcha and generate a new response token,\nthen you need to call `grecaptcha.reset()`.\n\n### `verify_recaptcha`\n\nThis method returns `true` or `false` after processing the response token from the reCAPTCHA widget.\nThis is usually called from your controller, as seen [above](#rails-installation).\n\nPassing in the ActiveRecord object via `model: object` is optional. If you pass a `model`—and the\ncaptcha fails to verify—an error will be added to the object for you to use (available as\n`object.errors`).\n\nWhy isn't this a model validation? Because that violates MVC. You can use it like this, or how ever\nyou like.\n\nSome of the options available:\n\n| Option                    | Description |\n|---------------------------|-------------|\n| `:model`                  | Model to set errors.\n| `:attribute`              | Model attribute to receive errors. (default: `:base`)\n| `:message`                | Custom error message.\n| `:secret_key`             | Override the secret API key from the configuration.\n| `:enterprise_api_key`     | Override the Enterprise API key from the configuration.\n| `:enterprise_project_id ` | Override the Enterprise project ID from the configuration.\n| `:timeout`                | The number of seconds to wait for reCAPTCHA servers before give up. (default: `3`)\n| `:response`               | Custom response parameter. (default: `params['g-recaptcha-response-data']`)\n| `:hostname`               | Expected hostname or a callable that validates the hostname, see [domain validation](https://developers.google.com/recaptcha/docs/domain_validation) and [hostname](https://developers.google.com/recaptcha/docs/verify#api-response) docs. (default: `nil`, but can be changed by setting `config.hostname`)\n| `:env`                    | Current environment. The request to verify will be skipped if the environment is specified in configuration under `skip_verify_env`\n| `:json`                   | Boolean; defaults to false; if true, will submit the verification request by POST with the request data in JSON\n\n\n### `invisible_recaptcha_tags`\n\nUse this when your key's reCAPTCHA type is \"v2 Invisible\".\n\nFor more information, refer to: [Invisible reCAPTCHA](https://developers.google.com/recaptcha/docs/invisible).\n\nThis is similar to `recaptcha_tags`, with the following additional options that are only available\non `invisible_recaptcha_tags`:\n\n| Option              | Description |\n|---------------------|-------------|\n| `:ui`               | The type of UI to render for this \"invisible\" widget. (default: `:button`)\u003cbr/\u003e`:button`: Renders a `\u003cbutton type=\"submit\"\u003e` tag with `options[:text]` as the button text.\u003cbr/\u003e`:invisible`: Renders a `\u003cdiv\u003e` tag.\u003cbr/\u003e`:input`: Renders a `\u003cinput type=\"submit\"\u003e` tag with `options[:text]` as the button text. |\n| `:text`             | The text to show for the button. (default: `\"Submit\"`)\n| `:inline_script`    | If you do not need this helper to add an inline script tag, you can set the option to `false` (default: `true`).\n\nIt also accepts most of the options that `recaptcha_tags` accepts, including the following:\n\n| Option              | Description |\n|---------------------|-------------|\n| `:site_key`         | Override site API key from configuration |\n| `:nonce`            | Optional. Sets nonce attribute for script tag. Can be generated via `SecureRandom.base64(32)`. Use `content_security_policy_nonce` if you have `config.content_security_policy_nonce_generator` set in Rails. (default: `nil`) |\n| `:id`               | Specify an html id attribute (default: `nil`) |\n| `:script`           | Same as setting both `:inline_script` and `:external_script`. If you only need one or the other, use `:inline_script` and `:external_script` instead. |\n| `:callback`         | Optional. Name of success callback function, executed when the user submits a successful response |\n| `:expired_callback` | Optional. Name of expiration callback function, executed when the reCAPTCHA response expires and the user needs to re-verify. |\n| `:error_callback`   | Optional. Name of error callback function, executed when reCAPTCHA encounters an error (e.g. network connectivity) |\n\n[JavaScript resource (api.js) parameters](https://developers.google.com/recaptcha/docs/invisible#js_param):\n\n| Option              | Description |\n|---------------------|-------------|\n| `:onload`           | Optional. The name of your callback function to be executed once all the dependencies have loaded. (See [explicit rendering](https://developers.google.com/recaptcha/docs/display#explicit_render)) |\n| `:render`           | Optional. Whether to render the widget explicitly. Defaults to `onload`, which will render the widget in the first g-recaptcha tag it finds. (See [explicit rendering](https://developers.google.com/recaptcha/docs/display#explicit_render)) |\n| `:hl`               | Optional. Forces the widget to render in a specific language. Auto-detects the user's language if unspecified. (See [language codes](https://developers.google.com/recaptcha/docs/language)) |\n| `:external_script`  | Set to `false` to avoid including a script tag for the external `api.js` resource. Useful when including multiple `recaptcha_tags` on the same page. |\n| `:script_async`     | Set to `false` to load the external `api.js` resource synchronously. (default: `true`) |\n| `:script_defer`     | Set to `false` to defer loading of external `api.js` until HTML documen has been parsed. (default: `true`) |\n\n### With a single form on a page\n\n1. The `invisible_recaptcha_tags` generates a submit button for you.\n\n```erb\n\u003c%= form_for @foo do |f| %\u003e\n  # ... other tags\n  \u003c%= invisible_recaptcha_tags text: 'Submit form' %\u003e\n\u003c% end %\u003e\n```\n\nThen, add `verify_recaptcha` to your controller as seen [above](#rails-installation).\n\n### With multiple forms on a page\n\n1. You will need a custom callback function, which is called after verification with Google's reCAPTCHA service. This callback function must submit the form. Optionally, `invisible_recaptcha_tags` currently implements a JS function called `invisibleRecaptchaSubmit` that is called when no `callback` is passed. Should you wish to override `invisibleRecaptchaSubmit`, you will need to use `invisible_recaptcha_tags script: false`, see lib/recaptcha/client_helper.rb for details.\n2. The `invisible_recaptcha_tags` generates a submit button for you.\n\n```erb\n\u003c%= form_for @foo, html: {id: 'invisible-recaptcha-form'} do |f| %\u003e\n  # ... other tags\n  \u003c%= invisible_recaptcha_tags callback: 'submitInvisibleRecaptchaForm', text: 'Submit form' %\u003e\n\u003c% end %\u003e\n```\n\n```javascript\n// app/assets/javascripts/application.js\nvar submitInvisibleRecaptchaForm = function () {\n  document.getElementById(\"invisible-recaptcha-form\").submit();\n};\n```\n\nFinally, add `verify_recaptcha` to your controller as seen [above](#rails-installation).\n\n### Programmatically invoke\n\n1. Specify `ui` option\n\n```erb\n\u003c%= form_for @foo, html: {id: 'invisible-recaptcha-form'} do |f| %\u003e\n  # ... other tags\n  \u003cbutton type=\"button\" id=\"submit-btn\"\u003e\n    Submit\n  \u003c/button\u003e\n  \u003c%= invisible_recaptcha_tags ui: :invisible, callback: 'submitInvisibleRecaptchaForm' %\u003e\n\u003c% end %\u003e\n```\n\n```javascript\n// app/assets/javascripts/application.js\ndocument.getElementById('submit-btn').addEventListener('click', function (e) {\n  // do some validation\n  if(isValid) {\n    // call reCAPTCHA check\n    grecaptcha.execute();\n  }\n});\n\nvar submitInvisibleRecaptchaForm = function () {\n  document.getElementById(\"invisible-recaptcha-form\").submit();\n};\n```\n\n\n## reCAPTCHA v3 API and Usage\n\nThe main differences from v2 are:\n1. you must specify an [action](https://developers.google.com/recaptcha/docs/v3#actions) in both frontend and backend\n1. you can choose the minimum score required for you to consider the verification a success\n   (consider the user a human and not a robot)\n1. reCAPTCHA v3 is invisible (except for the reCAPTCHA badge) and will never interrupt your users;\n   you have to choose which scores are considered an acceptable risk, and choose what to do (require\n   two-factor authentication, show a v3 challenge, etc.) if the score falls below the threshold you\n   choose\n\nFor more information, refer to the [v3 documentation](https://developers.google.com/recaptcha/docs/v3).\n\n### Examples\n\nWith v3, you can let all users log in without any intervention at all if their score is above some\nthreshold, and only show a v2 checkbox recaptcha challenge (fall back to v2) if it is below the\nthreshold:\n\nThis example sets v2 keys through environment variables. For more information on how to set up keys, please refer to the [documentation here](#alternative-api-key-setup).\n\n```bash\n# .env\nRECAPTCHA_SITE_KEY=6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy\nRECAPTCHA_SECRET_KEY=6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx\n```\n\n```erb\n  …\n  \u003c% if @show_checkbox_recaptcha %\u003e\n    \u003c%= recaptcha_tags %\u003e\n  \u003c% else %\u003e\n    \u003c%= recaptcha_v3(action: 'login', site_key: ENV['RECAPTCHA_SITE_KEY_V3']) %\u003e\n  \u003c% end %\u003e\n  …\n```\n\n```ruby\n# app/controllers/sessions_controller.rb\ndef create\n  success = verify_recaptcha(action: 'login', minimum_score: 0.5, secret_key: ENV['RECAPTCHA_SECRET_KEY_V3'])\n  checkbox_success = verify_recaptcha unless success\n  if success || checkbox_success\n    # Perform action\n  else\n    if !success\n      @show_checkbox_recaptcha = true\n    end\n    render 'new'\n  end\nend\n```\n\n(You can also find this [example](demo/rails/app/controllers/v3_captchas_controller.rb) in the demo app.)\n\nAnother example:\n\n```erb\n\u003c%= form_for @user do |f| %\u003e\n  …\n  \u003c%= recaptcha_v3(action: 'registration') %\u003e\n  …\n\u003c% end %\u003e\n```\n\n```ruby\n# app/controllers/users_controller.rb\ndef create\n  @user = User.new(params[:user].permit(:name))\n  recaptcha_valid = verify_recaptcha(model: @user, action: 'registration')\n  if recaptcha_valid\n    if @user.save\n      redirect_to @user\n    else\n      render 'new'\n    end\n  else\n    # Score is below threshold, so user may be a bot. Show a challenge, require multi-factor\n    # authentication, or do something else.\n    render 'new'\n  end\nend\n```\n\n\n### `recaptcha_v3`\n\nAdds an inline script tag that calls `grecaptcha.execute` for the given `site_key` and `action` and\ncalls the `callback` with the resulting response token. You need to verify this token with\n[`verify_recaptcha`](#verify_recaptcha-use-with-v3) in your controller in order to get the\n[score](https://developers.google.com/recaptcha/docs/v3#score).\n\nBy default, this inserts a hidden `\u003cinput type=\"hidden\" class=\"g-recaptcha-response\"\u003e` tag. The\nvalue of this input will automatically be set to the response token (by the default callback\nfunction). This lets you include `recaptcha_v3` within a `\u003cform\u003e` tag and have it automatically\nsubmit the token as part of the form submission.\n\nNote: reCAPTCHA actually already adds its own hidden tag, like `\u003ctextarea\nid=\"g-recaptcha-response-data-100000\" name=\"g-recaptcha-response-data\" class=\"g-recaptcha-response\"\u003e`,\nimmediately ater the reCAPTCHA badge in the bottom right of the page — but since it is not inside of\nany `\u003cform\u003e` element, and since it already passes the token to the callback, this hidden `textarea`\nisn't helpful to us.\n\nIf you need to submit the response token to the server in a different way than via a regular form\nsubmit, such as via [Ajax](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) or [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API),\nthen you can either:\n1. just extract the token out of the hidden `\u003cinput\u003e` or `\u003ctextarea\u003e` (both of which will have a\n   predictable name/id), like `document.getElementById('g-recaptcha-response-data-my-action').value`, or\n2. write and specify a custom `callback` function. You may also want to pass `element: false` if you\n   don't have a use for the hidden input element.\n\nNote that you cannot submit/verify the same response token more than once or you\nwill get a `timeout-or-duplicate` error code. If you need reset the captcha and\ngenerate a new response token, then you need to call `grecaptcha.execute(…)` or\n`grecaptcha.enterprise.execute(…)` again. This helper provides a JavaScript\nmethod (for each action) named `executeRecaptchaFor{action}` to make this\neasier. That is the same method that is invoked immediately. It simply calls\n`grecaptcha.execute` or `grecaptcha.enterprise.execute` again and then calls the\n`callback` function with the response token.\n\nYou will also get a `timeout-or-duplicate` error if too much time has passed between getting the\nresponse token and verifying it. This can easily happen with large forms that take the user a couple\nminutes to complete. Unlike v2, where you can use the `expired-callback` to be notified when the\nresponse expires, v3 appears to provide no such callback. See also\n[1](https://github.com/google/recaptcha/issues/281) and\n[2](https://stackoverflow.com/questions/54437745/recaptcha-v3-how-to-deal-with-expired-token-after-idle).\n\nTo deal with this, it is recommended to call the \"execute\" in your form's submit handler (or\nimmediately before sending to the server to verify if not using a form) rather than using the\nresponse token that gets generated when the page first loads. The `executeRecaptchaFor{action}`\nfunction mentioned above can be used if you want it to invoke a callback, or the\n`executeRecaptchaFor{action}Async` variant if you want a `Promise` that you can `await`. See\n[demo/rails/app/views/v3_captchas/index.html.erb](demo/rails/app/views/v3_captchas/index.html.erb)\nfor an example of this.\n\nThis helper is similar to the [`recaptcha_tags`](#recaptcha_tags)/[`invisible_recaptcha_tags`](#invisible_recaptcha_tags) helpers\nbut only accepts the following options:\n\n| Option              | Description |\n|---------------------|-------------|\n| `:site_key`         | Override site API key |\n| `:action`           | The name of the [reCAPTCHA action](https://developers.google.com/recaptcha/docs/v3#actions). Actions are not case-sensitive and may only contain alphanumeric characters, slashes, and underscores, and must not be user-specific. |\n| `:nonce`            | Optional. Sets nonce attribute for script. Can be generated via `SecureRandom.base64(32)`. Use `content_security_policy_nonce` if you have `config.content_security_policy_nonce_generator` set in Rails. (default: `nil`) |\n| `:callback`         | Name of callback function to call with the token. When `element` is `:input`, this defaults to a function named `setInputWithRecaptchaResponseTokenFor#{sanitize_action(action)}` that sets the value of the hidden input to the token. |\n| `:id`               | Specify a unique `id` attribute for the `\u003cinput\u003e` element if using `element: :input`. (default: `\"g-recaptcha-response-data-\"` + `action`) |\n| `:name`             | Specify a unique `name` attribute for the `\u003cinput\u003e` element if using `element: :input`. (default: `g-recaptcha-response-data[action]`) |\n| `:script`           | Same as setting both `:inline_script` and `:external_script`. (default: `true`). |\n| `:inline_script`    | If `true`, adds an inline script tag that calls `grecaptcha.execute` for the given `site_key` and `action` and calls the `callback` with the resulting response token. Pass `false` if you want to handle calling `grecaptcha.execute` yourself. (default: `true`) |\n| `:element`          | The element to render, if any (default: `:input`)\u003cbr/\u003e`:input`: Renders a hidden `\u003cinput type=\"hidden\"\u003e` tag. The value of this will be set to the response token by the default `setInputWithRecaptchaResponseTokenFor{action}` callback.\u003cbr/\u003e`false`: Doesn't render any tag. You'll have to add a custom callback that does something with the token. |\n| `:turbo`              | If `true`, calls the js function which executes reCAPTCHA after all the dependencies have been loaded. This cannot be used with the js param `:onload`. This makes reCAPTCHAv3 usable with turbo. |\n| `:turbolinks`         | Alias of `:turbo`. Will be deprecated soon. |\n| `:ignore_no_element`  | If `true`, adds null element checker for forms that can be removed from the page by javascript like modals with forms. (default: true) |\n\n[JavaScript resource (api.js) parameters](https://developers.google.com/recaptcha/docs/invisible#js_param):\n\n| Option              | Description |\n|---------------------|-------------|\n| `:onload`           | Optional. The name of your callback function to be executed once all the dependencies have loaded. (See [explicit rendering](https://developers.google.com/recaptcha/docs/display#explicit_render))|\n| `:external_script`  | Set to `false` to avoid including a script tag for the external `api.js` resource. Useful when including multiple `recaptcha_tags` on the same page.\n| `:script_async`     | Set to `true` to load the external `api.js` resource asynchronously. (default: `false`) |\n| `:script_defer`     | Set to `true` to defer loading of external `api.js` until HTML documen has been parsed. (default: `false`) |\n\nIf using `element: :input`, any unrecognized options will be added as attributes on the generated\n`\u003cinput\u003e` element.\n\n### `verify_recaptcha` (use with v3)\n\nThis works the same as for v2, except that you may pass an `action` and `minimum_score` if you wish\nto validate that the action matches or that the score is above the given threshold, respectively.\n\n```ruby\nresult = verify_recaptcha(action: 'action/name')\n```\n\n| Option           | Description |\n|------------------|-------------|\n| `:action`        | The name of the [reCAPTCHA action](https://developers.google.com/recaptcha/docs/v3#actions) that we are verifying. Set to `false` or `nil` to skip verifying that the action matches.\n| `:minimum_score` | Provide a threshold to meet or exceed. Threshold should be a float between 0 and 1 which will be tested as `score \u003e= minimum_score`. (Default: `nil`) |\n\n### Multiple actions on the same page\n\nAccording to https://developers.google.com/recaptcha/docs/v3#placement,\n\n\u003e Note: You can execute reCAPTCHA as many times as you'd like with different actions on the same page.\n\nYou will need to verify each action individually with a separate call to `verify_recaptcha`.\n\n```ruby\nresult_a = verify_recaptcha(action: 'a')\nresult_b = verify_recaptcha(action: 'b')\n```\n\nBecause the response tokens for multiple actions may be submitted together in the same request, they\nare passed as a hash under `params['g-recaptcha-response-data']` with the action as the key.\n\nIt is recommended to pass `external_script: false` on all but one of the calls to\n`recaptcha` since you only need to include the script tag once for a given `site_key`.\n\n## `recaptcha_reply` and `recaptcha_failure_reason`\n\nAfter `verify_recaptcha` has been called, you can call `recaptcha_reply` to get the raw reply from recaptcha. This can allow you to get the exact score returned by recaptcha should you need it.\n\n```ruby\nif verify_recaptcha(action: 'login')\n  redirect_to @user\nelse\n  score = recaptcha_reply['score']\n  Rails.logger.warn(\"User #{@user.id} was denied login because of a recaptcha score of #{score}\")\n  render 'new'\nend\n```\n\n`recaptcha_reply` will return `nil` if the the reply was not yet fetched.\n\n`recaptcha_failure_reason` will return information if verification failed. E.g. if params was wrong or api resulted some error-codes.\n\n## I18n support\n\nreCAPTCHA supports the I18n gem (it comes with English translations)\nTo override or add new languages, add to `config/locales/*.yml`\n\n```yaml\n# config/locales/en.yml\nen:\n  recaptcha:\n    errors:\n      verification_failed: 'reCAPTCHA was incorrect, please try again.'\n      recaptcha_unreachable: 'reCAPTCHA verification server error, please try again.'\n```\n\n## Testing\n\nBy default, reCAPTCHA is skipped in \"test\" and \"cucumber\" env. To enable it during test:\n\n```ruby\nRecaptcha.configuration.skip_verify_env.delete(\"test\")\n```\n\n## Alternative API key setup\n\n### Recaptcha.configure\n\n```ruby\n# config/initializers/recaptcha.rb\nRecaptcha.configure do |config|\n  config.site_key  = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'\n  config.secret_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'\n\n  # Uncomment the following line if you are using a proxy server:\n  # config.proxy = 'http://myproxy.com.au:8080'\n\n  # Uncomment the following lines if you are using the Enterprise API:\n  # config.enterprise = true\n  # config.enterprise_api_key = 'AIzvFyE3TU-g4K_Kozr9F1smEzZSGBVOfLKyupA'\n  # config.enterprise_project_id = 'my-project'\nend\n```\n\n### Recaptcha.with_configuration\n\nFor temporary overwrites (not thread-safe).\n\n```ruby\nRecaptcha.with_configuration(site_key: '12345') do\n  # Do stuff with the overwritten site_key.\nend\n```\n\n### Per call\n\nPass in keys as options at runtime, for code base with multiple reCAPTCHA setups:\n\n```ruby\nrecaptcha_tags site_key: '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'\n\n# and\n\nverify_recaptcha secret_key: '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'\n```\n\n\n## hCaptcha support\n\n[hCaptcha](https://hcaptcha.com) is an alternative service providing reCAPTCHA API.\n\nTo use hCaptcha:\n1. Set a site and a secret key as usual\n2. Set two options in `verify_url` and `api_service_url` pointing to hCaptcha API endpoints.\n3. Disable a response limit check by setting a `response_limit` to the large enough value (reCAPTCHA is limited by 4000 characters).\n4. It is not required to change a parameter name as [official docs suggest](https://docs.hcaptcha.com/switch) because API handles standard `g-recaptcha` for compatibility.\n\n```ruby\n# config/initializers/recaptcha.rb\nRecaptcha.configure do |config|\n  config.site_key  = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'\n  config.secret_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'\n  config.verify_url = 'https://hcaptcha.com/siteverify'\n  config.api_server_url = 'https://hcaptcha.com/1/api.js'\n  config.response_limit = 100000\n  config.response_minimum = 100\nend\n```\n\nhCaptcha uses a scoring system (higher number more likely to be a bot) which is inverse of the reCaptcha scoring system (lower number more likely to be a bot). As such, a `maximum_score` attribute is provided for use with hCaptcha.\n\n```ruby\nresult = verify_recaptcha(maximum_score: 0.7)\n```\n\n| Option           | Description |\n|------------------|-------------|\n| `:maximum_score` | Provide a threshold to meet or fall below. Threshold should be a float between 0 and 1 which will be tested as `score \u003c= maximum_score`. (Default: `nil`) |\n\n## Misc\n - Check out the [wiki](https://github.com/ambethia/recaptcha/wiki) and leave whatever you found valuable there.\n - [Add multiple widgets to the same page](https://github.com/ambethia/recaptcha/wiki/Add-multiple-widgets-to-the-same-page)\n - [Use Recaptcha with Devise](https://github.com/plataformatec/devise/wiki/How-To:-Use-Recaptcha-with-Devise)\n","funding_links":[],"categories":["Security","Biblioteki","Ruby","Captchas and anti-spam"],"sub_categories":["Rails Captcha"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fambethia%2Frecaptcha","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fambethia%2Frecaptcha","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fambethia%2Frecaptcha/lists"}