[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-8073":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":16,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":17,"rankGlobal":10,"rankLanguage":10,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":21,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":27,"readmeContent":28,"aiSummary":29,"trendingCount":16,"starSnapshotCount":16,"syncStatus":30,"lastSyncTime":31,"discoverSource":32},8073,"recaptcha","ambethia\u002Frecaptcha","ambethia","ReCaptcha helpers for ruby apps","http:\u002F\u002Fgithub.com\u002Fambethia\u002Frecaptcha",null,"Ruby",2004,438,23,51,0,59.93,"MIT License",false,"master",true,[23,24,5,25,26],"captcha","rails","ruby","sinatra","2026-06-12 04:00:37","\n# reCAPTCHA\n[![Gem Version](https:\u002F\u002Fbadge.fury.io\u002Frb\u002Frecaptcha.svg)](https:\u002F\u002Fbadge.fury.io\u002Frb\u002Frecaptcha)\n\nAuthor:    Jason L Perry (http:\u002F\u002Fambethia.com)\u003Cbr\u002F>\nCopyright: Copyright (c) 2007-2013 Jason L Perry\u003Cbr\u002F>\nLicense:   [MIT](http:\u002F\u002Fcreativecommons.org\u002Flicenses\u002FMIT\u002F)\u003Cbr\u002F>\nInfo:      https:\u002F\u002Fgithub.com\u002Fambethia\u002Frecaptcha\u003Cbr\u002F>\nBugs:      https:\u002F\u002Fgithub.com\u002Fambethia\u002Frecaptcha\u002Fissues\u003Cbr\u002F>\n\nThis gem provides helper methods for the [reCAPTCHA API](https:\u002F\u002Fwww.google.com\u002Frecaptcha). 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 \u002F Rack \u002F Ruby Installation](#sinatra--rack--ruby-installation)\n4. [reCAPTCHA V2 API & 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 & 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:\u002F\u002Fwww.google.com\u002Frecaptcha\u002Fadmin) 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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fv3#score)\n| v2 Checkbox\u003Cbr\u002F>(\"I'm not a robot\" Checkbox) | [`recaptcha_tags`](#recaptcha_tags)                     | Validate requests with the \"I'm not a robot\" checkbox |\n| v2 Invisible\u003Cbr\u002F>(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:\u002F\u002Fgithub.com\u002Fambethia\u002Frecaptcha\u002Fwiki\u002FRecaptcha-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:\u002F\u002Fapi.rubyonrails.org\u002Fclasses\u002FRails\u002FApplication.html#method-i-secrets).\u003Cbr\u002F>\n\nIn development, you can use the [dotenv](https:\u002F\u002Fgithub.com\u002Fbkeepers\u002Fdotenv) 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:\u002F\u002Fwww.rubydoc.info\u002Fgithub\u002Fambethia\u002Frecaptcha\u002Fmaster\u002FRecaptcha\u002FConfiguration)\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:\u002F\u002Fconsole.cloud.google.com\u002Fapis\u002Fcredentials.\n\nAdd `recaptcha_tags` to the forms you want to protect:\n\n```erb\n\u003C%= form_for @foo do |f| %>\n  # …\n  \u003C%= recaptcha_tags %>\n  # …\n\u003C% end %>\n```\n\nThen, add `verify_recaptcha` logic to each form action that you've protected:\n\n```ruby\n# app\u002Fcontrollers\u002Fusers_controller.rb\n@user = User.new(params[:user].permit(:name))\nif verify_recaptcha(model: @user) && @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 \u002F Rack \u002F Ruby installation\n\nSee [sinatra demo](\u002Fdemo\u002Fsinatra) 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>` content (default: `true`)|\n\n[JavaScript resource (api.js) parameters](https:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Finvisible#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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fdisplay#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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fdisplay#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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Flanguage)) |\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:\u002F\u002Fgithub.com\u002Fambethia\u002Frecaptcha\u002Fblob\u002Fmaster\u002Flib\u002Frecaptcha\u002Fhelpers.rb)\nto see these options.\n\nNote that you cannot submit\u002Fverify 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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fdomain_validation) and [hostname](https:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fverify#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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Finvisible).\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\u002F>`:button`: Renders a `\u003Cbutton type=\"submit\">` tag with `options[:text]` as the button text.\u003Cbr\u002F>`:invisible`: Renders a `\u003Cdiv>` tag.\u003Cbr\u002F>`:input`: Renders a `\u003Cinput type=\"submit\">` 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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Finvisible#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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fdisplay#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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fdisplay#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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Flanguage)) |\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| %>\n  # ... other tags\n  \u003C%= invisible_recaptcha_tags text: 'Submit form' %>\n\u003C% end %>\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\u002Frecaptcha\u002Fclient_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| %>\n  # ... other tags\n  \u003C%= invisible_recaptcha_tags callback: 'submitInvisibleRecaptchaForm', text: 'Submit form' %>\n\u003C% end %>\n```\n\n```javascript\n\u002F\u002F app\u002Fassets\u002Fjavascripts\u002Fapplication.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| %>\n  # ... other tags\n  \u003Cbutton type=\"button\" id=\"submit-btn\">\n    Submit\n  \u003C\u002Fbutton>\n  \u003C%= invisible_recaptcha_tags ui: :invisible, callback: 'submitInvisibleRecaptchaForm' %>\n\u003C% end %>\n```\n\n```javascript\n\u002F\u002F app\u002Fassets\u002Fjavascripts\u002Fapplication.js\ndocument.getElementById('submit-btn').addEventListener('click', function (e) {\n  \u002F\u002F do some validation\n  if(isValid) {\n    \u002F\u002F 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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fv3#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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fv3).\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 %>\n    \u003C%= recaptcha_tags %>\n  \u003C% else %>\n    \u003C%= recaptcha_v3(action: 'login', site_key: ENV['RECAPTCHA_SITE_KEY_V3']) %>\n  \u003C% end %>\n  …\n```\n\n```ruby\n# app\u002Fcontrollers\u002Fsessions_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\u002Frails\u002Fapp\u002Fcontrollers\u002Fv3_captchas_controller.rb) in the demo app.)\n\nAnother example:\n\n```erb\n\u003C%= form_for @user do |f| %>\n  …\n  \u003C%= recaptcha_v3(action: 'registration') %>\n  …\n\u003C% end %>\n```\n\n```ruby\n# app\u002Fcontrollers\u002Fusers_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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fv3#score).\n\nBy default, this inserts a hidden `\u003Cinput type=\"hidden\" class=\"g-recaptcha-response\">` 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>` 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\">`,\nimmediately ater the reCAPTCHA badge in the bottom right of the page — but since it is not inside of\nany `\u003Cform>` 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:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FXMLHttpRequest) or [`fetch`](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FFetch_API),\nthen you can either:\n1. just extract the token out of the hidden `\u003Cinput>` or `\u003Ctextarea>` (both of which will have a\n   predictable name\u002Fid), 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\u002Fverify 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:\u002F\u002Fgithub.com\u002Fgoogle\u002Frecaptcha\u002Fissues\u002F281) and\n[2](https:\u002F\u002Fstackoverflow.com\u002Fquestions\u002F54437745\u002Frecaptcha-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\u002Frails\u002Fapp\u002Fviews\u002Fv3_captchas\u002Findex.html.erb](demo\u002Frails\u002Fapp\u002Fviews\u002Fv3_captchas\u002Findex.html.erb)\nfor an example of this.\n\nThis helper is similar to the [`recaptcha_tags`](#recaptcha_tags)\u002F[`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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fv3#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>` element if using `element: :input`. (default: `\"g-recaptcha-response-data-\"` + `action`) |\n| `:name`             | Specify a unique `name` attribute for the `\u003Cinput>` 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\u002F>`:input`: Renders a hidden `\u003Cinput type=\"hidden\">` tag. The value of this will be set to the response token by the default `setInputWithRecaptchaResponseTokenFor{action}` callback.\u003Cbr\u002F>`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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Finvisible#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:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fdisplay#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>` 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\u002Fname')\n```\n\n| Option           | Description |\n|------------------|-------------|\n| `:action`        | The name of the [reCAPTCHA action](https:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fv3#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 >= minimum_score`. (Default: `nil`) |\n\n### Multiple actions on the same page\n\nAccording to https:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fv3#placement,\n\n> 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\u002Flocales\u002F*.yml`\n\n```yaml\n# config\u002Flocales\u002Fen.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\u002Finitializers\u002Frecaptcha.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:\u002F\u002Fmyproxy.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:\u002F\u002Fhcaptcha.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:\u002F\u002Fdocs.hcaptcha.com\u002Fswitch) because API handles standard `g-recaptcha` for compatibility.\n\n```ruby\n# config\u002Finitializers\u002Frecaptcha.rb\nRecaptcha.configure do |config|\n  config.site_key  = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'\n  config.secret_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'\n  config.verify_url = 'https:\u002F\u002Fhcaptcha.com\u002Fsiteverify'\n  config.api_server_url = 'https:\u002F\u002Fhcaptcha.com\u002F1\u002Fapi.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:\u002F\u002Fgithub.com\u002Fambethia\u002Frecaptcha\u002Fwiki) and leave whatever you found valuable there.\n - [Add multiple widgets to the same page](https:\u002F\u002Fgithub.com\u002Fambethia\u002Frecaptcha\u002Fwiki\u002FAdd-multiple-widgets-to-the-same-page)\n - [Use Recaptcha with Devise](https:\u002F\u002Fgithub.com\u002Fplataformatec\u002Fdevise\u002Fwiki\u002FHow-To:-Use-Recaptcha-with-Devise)\n","ambethia\u002Frecaptcha 是一个为 Ruby 应用提供 reCAPTCHA 集成支持的 gem。它通过 `recaptcha_tags` 方法在视图中嵌入必要的 JavaScript 代码，并使用 `verify_recaptcha` 或 `verify_recaptcha!` 在控制器中验证 reCAPTCHA 的有效性，后者会在验证失败时抛出异常。该项目兼容 reCAPTCHA V2 和 V3 API，支持多种验证方式如复选框、“I'm not a robot” 检查以及隐形 reCAPTCHA 徽章。适用于需要防止机器人滥用表单提交功能的各种 Web 应用场景，尤其是基于 Ruby on Rails 或 Sinatra 构建的应用程序。",2,"2026-06-11 03:15:55","top_language"]