reCAPTCHA - error-codes: 'missing-input-response', 'missing-input-secret' when verifying user's response (missing details on POST) reCAPTCHA - error-codes: 'missing-input-response', 'missing-input-secret' when verifying user's response (missing details on POST) express express

reCAPTCHA - error-codes: 'missing-input-response', 'missing-input-secret' when verifying user's response (missing details on POST)


Doing a bit of research and digging around the reCaptcha Google forums, It seems that this endpoint only accepts the default content type; application/x-www-form-urlencoded.

Which means you should not use JSON to send your response token and site key. Instead, send the value as how the application/x-www-form-urlencoded defined:

Forms submitted with this content type must be encoded as follows:

  1. Control names and values are escaped. Space characters are replaced by '+', and then reserved characters are escaped as described in [RFC1738], section 2.2: Non-alphanumeric characters are replaced by '%HH', a percent sign and two hexadecimal digits representing the ASCII code of the character. Line breaks are represented as "CR LF" pairs (i.e., '%0D%0A').
  2. The control names/values are listed in the order they appear in the document. The name is separated from the value by '=' and name/value pairs are separated from each other by '&'.

Therefore, you got two ways of doing this, either by passing the POST parameters through the URL (query strings) and sending it as a POST request:

https://www.google.com/recaptcha/api/siteverify?secret=${SECRET_KEY}&response=${req.body['g-recaptcha-response']}

or appending the data to the body manually like so:

verify(req, res, next) {  const VERIFY_URL = "https://www.google.com/recaptcha/api/siteverify";  return fetch(VERIFY_URL, {    method: "POST",    headers: { "Content-Type": "application/x-www-form-urlencoded" },    body: `secret=${SECRET_KEY}&response=${req.body['g-recaptcha-response']}`,  })  .then(response => response.json())  .then(data => {    res.locals.recaptcha = data;    return next();  });}

The official Google documentation can be found here:
Recaptcha - Verifying the user's response.


Extending on U-ways answer above (thanks for that), if you wanted to keep a JS object structure instead of formatting inline params, you could make use of URLSearchParams and Object.entries:

const recaptchaBody = {  secret: RECAPTCHA_SECRET,  response: recaptchaResponse,};// Check recaptcha validityfetch("https://www.google.com/recaptcha/api/siteverify", {  method: "POST",  headers: { "Content-Type": "application/x-www-form-urlencoded" },  body: new URLSearchParams(Object.entries(recaptchaBody)).toString(),}).then((res) => res.json()).then((data) => {  // If it's not a success..  if (!data?.success) {    // ERROR  }});