WordPress REST API error

rest_cookie_invalid_nonce.

This error means WordPress reached cookie/session authentication, but the X-WP-Nonce value did not validate for the current logged-in session.

Failure stage

Endpoint reached: the request got to WordPress REST handling.
Cookie auth attempted: WordPress treated the browser session as the auth path.
Failed first: the nonce is stale, missing, generated for the wrong action, or from another session.
Not reached yet: route permission callback and business logic may not have run.

Nonce evidence matrix

EvidenceLikely causeFirst check
{"code":"rest_cookie_invalid_nonce"}Cookie nonce rejectedRegenerate nonce with wp_create_nonce('wp_rest').
X-WP-Nonce present but still 403Nonce from another user/sessionGenerate it in the same logged-in browser that sends the request.
Works after refresh, fails laterCached or expired nonceDo not cache localized nonce values for long-lived pages.
External script sends nonceWrong auth modelUse Application Passwords instead of browser cookie nonces.
Request is cross-originCookie not sent or blockedCheck same-origin path, credentials mode, and cookie policy.

Do this first

Do this

  • Confirm the request is same-origin and sent by a logged-in user.
  • Regenerate the nonce immediately before the page script uses it.
  • Send it as X-WP-Nonce, not inside a JSON body.
  • Use the REST debugger with the exact response JSON.

Do not do this yet

  • Do not loosen permission_callback to bypass the nonce error.
  • Do not switch to admin cookies for external scripts.
  • Do not treat this as a route-not-found problem.
  • Do not disable security plugins until nonce/session evidence is checked.

Bad request pattern

fetch('/wp-json/my-plugin/v1/save', {
  method: 'POST',
  headers: { 'X-WP-Nonce': cachedNonceFromYesterday },
  body: JSON.stringify({ title: 'Draft' })
});

Corrected pattern

// Pattern to verify in your environment.
wp_localize_script('my-app', 'IFK_REST', [
    'root' => esc_url_raw(rest_url()),
    'nonce' => wp_create_nonce('wp_rest'),
]);

fetch(IFK_REST.root + 'my-plugin/v1/save', {
  method: 'POST',
  credentials: 'same-origin',
  headers: {
    'Content-Type': 'application/json',
    'X-WP-Nonce': IFK_REST.nonce
  },
  body: JSON.stringify({ title: 'Draft' })
});