Checkout Bouncer

Notes

reCAPTCHA classic and reCAPTCHA Enterprise: which one your keys are for

Google runs two products under the reCAPTCHA name, in two consoles, with two different verification APIs. Here is how to tell which one your keys belong to, and what follows from that.

6 min read

Google now ships two products under one name, and reCAPTCHA Enterprise is the half that most current documentation describes. The other half is the classic product. It has a site key, a secret key and a check endpoint that has barely changed in years. Both of them score traffic. But they live in different consoles. They plug in through different APIs. And Google keeps their docs in separate trees. So a checkout guard set up against the wrong tree can fail in a way that looks like nothing at all.

Because the naming gives you no warning, the first job is working out which of the two your own keys belong to.

Two consoles, two products

First, classic keys live in the reCAPTCHA admin console at g.co/recaptcha/admin. reCAPTCHA Enterprise keys live inside a Google Cloud project instead, on the Fraud Defense page of the Google Cloud console. Google's migration page offers a one-line test: "If you manage your keys in the reCAPTCHA Admin console, then you're using reCAPTCHA Classic."

That really is the whole diagnostic. If seeing your keys means signing in to Google Cloud, choosing a project and looking at a billing account, then you are on the other side of the line.

Meanwhile the classic pages show the split in a second way. Each of them now carries a banner reading "This page is deprecated. See the Google Cloud Fraud Defense documentation page for additional information." Those pages are still correct about the classic setup. And every older tutorial still links to them. Yet a reader who follows the banner lands in a tree about a different one. That is how the muddle starts.

What the front end tells you

Before anything else, read your own page source. Classic loads api.js from www.google.com/recaptcha/ and calls grecaptcha.execute(). Enterprise loads enterprise.js from the same host and calls grecaptcha.enterprise.execute() instead.

So the script filename is a solid tell. And the shape of the call confirms it. Neither one asks you to recall which console you used two years ago.

Classic verification posts to siteverify

On the server, classic verification is a single form post. Specifically, Google's reference gives the URL as https://www.google.com/recaptcha/api/siteverify and the method as POST. It takes secret, described as "The shared key between your site and reCAPTCHA", plus response, which is the token, and an optional remoteip. Back comes a small flat JSON object carrying success, score, action, hostname and any error codes.

No project, no credentials, no client library. Any language that can post a form can do it. That is one reason the classic flow ended up inside so many plugins. Which key goes where, and what the error codes mean, is a separate matter.

reCAPTCHA Enterprise creates an assessment

The Enterprise path swaps that post for a call to a Google Cloud API. You create what the docs call an assessment, by posting to https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessments. The body is not a form. Rather it is JSON with an event object holding token, siteKey and expectedAction.

Then comes the sign-in step. That is where the two really part company. Notably, there is no secret to post. Instead, Google Cloud credentials sign the request, either a bearer token from a service account or an API key. Further, the caller needs the role the docs name as "reCAPTCHA Enterprise Agent (roles/recaptchaenterprise.agent)". So this is not a drop-in swap. Nothing about it fits in the same two text boxes.

Both give a score, in different wrappers

For the score-based case, the two answer the same question. Classic v3 "returns a score (1.0 is very likely a good interaction, 0.0 is very likely a bot)". The Enterprise page says more: "The score 1.0 indicates that the interaction poses low risk and is very likely legitimate, whereas 0.0 indicates that the interaction poses high risk and might be fraudulent."

Still, the wrapper differs. Classic returns score at the top level. An assessment nests it under riskAnalysis.score, next to tokenProperties.valid and an invalidReason when the token did not check out. The steps differ too. Google states that "reCAPTCHA has 11 levels for scores with values ranging from 0.0 to 1.0", and adds that "Out of the 11 levels, only the following four score levels are available before triggering an automatic security review by adding a billing account to your project: 0.1, 0.3, 0.7, and 0.9."

Either way, where you draw the line is the same job. And choosing a threshold on your own traffic covers it.

What this means for a WordPress plugin

In practice, a plugin built for classic keys asks for two strings and posts them to siteverify. One built for reCAPTCHA Enterprise needs a project ID, a cloud credential and a lot more code. Those are not the same settings screen. An Enterprise key in a classic plugin still renders a page and still checks nothing. So the widget on screen is no evidence that anything behind it worked.

There is one useful bridge, though, and Google spells it out. A key made in Google Cloud still gets a classic-style secret: "For every site key that you create, reCAPTCHA creates a legacy reCAPTCHA secret key (legacy secret key), which you can use with your third-party application." The same page notes that "Third-party applications or plugins often refer to this legacy secret key as a private key or secret key." It runs the other way as well. After you move a classic key to Google Cloud, "you can continue to use the siteverify method to assess a user's reCAPTCHA response token."

For most stores, then, the answer is to change nothing. Make a score-based key of the kind your plugin actually supports. Then keep the pair together, and read the doc tree that matches it.

Where Checkout Bouncer fits

Checkout Bouncer works with a classic reCAPTCHA v3 key pair and nothing else. It takes a site key and a secret key, loads the classic script, and checks the token against siteverify on the request that places the order. The plugin is free, GPL and listed on WordPress.org.

Its limits want stating flatly. Namely, the plugin does not support reCAPTCHA Enterprise, and no v2, hCaptcha or Turnstile key will work either. It guards the WooCommerce checkout and nothing else. So login, sign-up, comments and contact forms need another tool. Nor does it act as a firewall or a malware scanner.

Google's own pages stay the authority here: the classic v3 overview, the siteverify reference, and on the cloud side the migration overview, creating an assessment and interpreting one. Meanwhile, if you want to know which routes into your checkout now answer, the free scanner takes about two minutes.

See which doors into your checkout are standing open