Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Use a WordPress nonce to reduce cross-site request forgery (CSRF) risk on a state-changing request. Create it with a specific action name, verify it in the same context in which it was issued, then perform a separate capability check and validate the submitted data. A nonce proves that WordPress generated the page or script; it does not authenticate a user or grant permission.

What a WordPress nonce does—and does not do

WordPress calls these values “nonces,” but they are hash-based tokens rather than strictly numeric values. They help show that a request came from a page or script generated by WordPress, which makes forged requests from another site harder to execute.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A nonce is one layer in a request’s defense. It is not a password, login credential, access-control decision, or proof that the current user owns the target record. WordPress’s developer documentation explicitly warns that nonces must never be relied on for authentication, authorization, or access control. Keep those responsibilities separate:

  • Nonce: helps mitigate CSRF by tying a request to a WordPress-generated context and action.
  • Authentication: establishes who is making the request, usually through a logged-in session or another authentication method.
  • Authorization: determines whether that user may perform the operation, typically with current_user_can().
  • Input handling: validates and sanitizes every value before using it.

Nonces are not strictly single-use, despite the name. A valid token can be accepted more than once during its validity window, so do not use one as a replay-prevention mechanism for payments, password resets, or other operations that require one-time credentials.

Choose an action string before creating the nonce

The action string identifies what the token protects. Make it specific to the operation and, where practical, the object involved. A value such as delete-comment_123 is safer to reason about than a generic action like save, because a token issued for one purpose should not be accidentally accepted for another.

Use the same exact action string when creating and verifying the token. Differences in spelling, punctuation, capitalization, or an object ID produce a mismatch.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
$action = 'delete-comment_123';
$nonce = wp_create_nonce( $action );

wp_create_nonce() returns the token value. Choose this form when you need to place the value into custom markup, a JavaScript configuration object, or a request built by your own code.

Generate a hidden form field

For a traditional HTML form, wp_nonce_field() prints hidden inputs containing the nonce. The first argument is the action. The optional second argument controls the field name; leaving it at its default creates the conventional _wpnonce field.

<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
    <input type="hidden" name="action" value="my_save_settings">
    <?php wp_nonce_field( 'save-settings' ); ?>
    <!-- Other validated fields go here. -->
    <button type="submit">Save</button>
</form>

Escape a generated URL when outputting it, and treat every user-supplied form value as untrusted even though the form includes a valid nonce.

Add a nonce to an administrative URL

For links that trigger an administrative action, use wp_nonce_url(). It appends a nonce query argument to the URL so the destination can verify the action.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
$url = wp_nonce_url(
    admin_url( 'admin-post.php?action=delete_comment&comment_id=123' ),
    'delete-comment_123'
);

echo '<a href="' . esc_url( $url ) . '">Delete comment</a>';

Protect destructive operations with an authorization check at the destination as well. A signed-looking URL should never be treated as permission to delete data.

Protect admin forms and links

Use check_admin_referer() when processing a form or URL in an administrative request. Pass the same action string used during creation. The function checks the request’s nonce and stops processing when verification fails under its normal behavior.

function my_save_settings() {
    check_admin_referer( 'save-settings' );

    if ( ! current_user_can( 'manage_options' ) ) {
        wp_die( 'You are not allowed to change these settings.' );
    }

    $label = isset( $_POST['label'] )
        ? sanitize_text_field( wp_unslash( $_POST['label'] ) )
        : '';

    // Validate the value and save it only after all checks pass.
}
add_action( 'admin_post_my_save_settings', 'my_save_settings' );

The sequence matters. Verify the nonce early, check the capability before changing data, and validate each field for the expected type, range, and format. For an ID, convert and validate an integer; for a status value, allow only the documented values; for text, apply the sanitizer appropriate to the field.

Handling a nonce failure

A failed administrative check should prevent the operation. Do not continue with a best-effort save or delete after verification fails. If your workflow needs a custom error page or logging behavior, use lower-level verification and return your own response rather than performing the state change.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Verify nonces in AJAX requests

AJAX requests need the same action-specific token as a regular form, but the verification helper is different. Use check_ajax_referer() in the server-side callback. The second argument is the request field containing the token; choose a name and send it consistently from the browser.

function my_delete_comment_ajax() {
    check_ajax_referer( 'delete-comment_123', 'security' );

    if ( ! current_user_can( 'moderate_comments' ) ) {
        wp_send_json_error( array( 'message' => 'Not allowed.' ), 403 );
    }

    $comment_id = isset( $_POST['comment_id'] )
        ? absint( $_POST['comment_id'] )
        : 0;

    if ( ! $comment_id ) {
        wp_send_json_error( array( 'message' => 'Invalid comment ID.' ), 400 );
    }

    // Confirm that the comment exists and that this operation is valid.
    // Delete only after all checks succeed.
    wp_send_json_success();
}
add_action( 'wp_ajax_my_delete_comment', 'my_delete_comment_ajax' );

For a logged-in AJAX action, the browser can receive a token through localized script data, an inline configuration object, or another server-rendered value. The client then posts that value with the action request.

const data = new URLSearchParams({
  action: 'my_delete_comment',
  comment_id: String(commentId),
  security: window.myPlugin.deleteCommentNonce
});

fetch(window.ajaxurl, {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
  body: data
});

With its default settings, check_ajax_referer() terminates the request when verification fails. On success it returns 1 for a token generated zero to 12 hours earlier and 2 for one generated 12 to 24 hours earlier. That return value can help you decide whether to refresh a token, but it does not replace a capability check.

When an endpoint needs a JSON error format or another custom failure path, use wp_verify_nonce() and handle the Boolean result yourself. Always return an error before any write operation if the result is false.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Send a nonce to the WordPress REST API

REST cookie authentication uses the logged-in WordPress session. For a browser request made inside that session, create a nonce with the action wp_rest and send it on every manual request in the X-WP-Nonce header. WordPress also accepts the token in an _wpnonce request parameter.

$rest_nonce = wp_create_nonce( 'wp_rest' );

Expose that value to the script using your normal server-to-client configuration technique, then include it in the request:

fetch('/wp-json/myplugin/v1/items/123', {
  method: 'DELETE',
  headers: {
    'X-WP-Nonce': window.myPlugin.restNonce,
    'Accept': 'application/json'
  }
});

WordPress’s REST cookie check is performed by rest_cookie_check_errors(). If the cookie-authenticated request has no valid REST nonce, WordPress treats it as unauthenticated. A missing token therefore commonly results in a permission failure even when the browser is visibly logged in.

REST nonce scope and alternatives

The wp_rest nonce is for cookie-authenticated REST requests made within a WordPress session. It is not a universal REST credential and should not be embedded as a permanent secret in a mobile app or distributed integration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Application passwords are a separate authentication option available since WordPress 5.6. Choose an authentication method that matches the client: use the REST nonce for same-origin, session-based browser interactions, and use an appropriate API authentication method for an external client. Regardless of authentication method, the endpoint must enforce its own permission callback and validate request data.

Nonce lifetime, sessions, and logged-out visitors

Default validity is 12 to 24 hours

The default nonce lifetime is described as one day, but WordPress divides that period into two half-life ticks. Consequently, a nonce is normally valid for a variable period between 12 and 24 hours, depending on when it was created relative to the tick boundary. Do not present the one-day setting as an exact 24-hour guarantee.

A token generated near the start of a tick can remain valid through the current and next tick; one generated near the end can expire soon after the next tick begins. If a long-lived page contains a nonce, design the client to recover from expiration instead of assuming the original markup remains valid indefinitely.

Tokens follow the current user session

Nonces are tied to the current user session. If a user logs in or out asynchronously, a token already rendered in the page may no longer validate for the new session state. Refresh the page or obtain a newly generated token after a session transition before retrying a state-changing request.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Logged-out users need additional protection

For visitors who are not logged in, WordPress defaults the nonce user identity to user ID 0. That means all anonymous visitors can otherwise share the same identity basis. For a critical guest action, add a separate guest-session mechanism through the nonce_user_logged_out filter, such as a server-managed session identifier. The nonce alone is not enough to distinguish anonymous users for sensitive workflows.

Choose the verification helper that matches the request

Request context Create the token Verify it Typical failure behavior Additional requirement
Administrative form wp_nonce_field( 'action' ) check_admin_referer( 'action' ) Stops processing under normal helper behavior Check the user’s capability and validate fields
Administrative URL wp_nonce_url( $url, 'action' ) check_admin_referer( 'action' ) Stops processing under normal helper behavior Check permission before the destructive operation
AJAX callback wp_create_nonce( 'action' ) check_ajax_referer( 'action', 'field' ) Terminates by default on failure Check capability, sanitize input, and return a suitable response
Custom handling wp_create_nonce( 'action' ) wp_verify_nonce( $value, 'action' ) Your code decides how to report failure Do not proceed when the result is false
REST API with cookie authentication wp_create_nonce( 'wp_rest' ) REST cookie authentication checks the nonce Missing or invalid token is treated as unauthenticated Send X-WP-Nonce or _wpnonce, then enforce endpoint permissions
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common nonce failures and their fixes

“Are you sure you want to do this?” or a failed admin check

This generally means the submitted token is missing, expired, or was created with a different action string. Confirm that the form includes wp_nonce_field(), that the request reaches the intended handler, and that creation and verification use an identical action. Reload the page if it has been open for more than the token’s validity window.

AJAX returns a nonce error

Inspect the outgoing request and confirm that the token field name matches the second argument to check_ajax_referer(). Also verify that the JavaScript is using a token generated for the same action and that a login or logout event has not replaced the session.

REST requests act as unauthenticated

For cookie-based REST authentication, check that the browser is sending its WordPress login cookies and that every request includes X-WP-Nonce with a value created using wp_rest. Sending a nonce generated for an AJAX or admin action will not satisfy the REST check. External clients should use a suitable authentication method rather than copying a browser session token.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The nonce passes but the operation is still denied

That is expected when the user lacks the required capability or the endpoint’s permission callback rejects the request. Add or correct the authorization check; never weaken it because the nonce is valid.

A guest action works for one visitor but is not adequately isolated

Anonymous requests use user ID 0 by default. Add a guest-session value through nonce_user_logged_out for critical actions and still validate the action’s business rules, rate limits, and submitted data.

Security checklist for plugin and theme code

  • Use a context-rich action string, ideally including the resource identifier when a token protects one object.
  • Create the nonce with the helper suited to the output: field, URL, or raw value.
  • Verify it with the matching admin, AJAX, REST, or custom helper.
  • Reject the request before changing state when verification fails.
  • Use current_user_can() or the endpoint’s permission callback for authorization.
  • Validate IDs, enumerated values, lengths, ownership, and other business rules independently of the nonce.
  • Sanitize values at the point where WordPress expects sanitized data, and escape values when outputting HTML or URLs.
  • Plan for expiration, session changes, and stale pages.
  • Use an additional guest-session mechanism for sensitive logged-out workflows.
  • Do not describe a nonce as single-use, an authentication credential, or an access-control mechanism.

Deploy and test nonce-protected changes safely

Test nonce-protected plugin or application changes in a staging environment before production. Take a backup before significant plugin or application changes so you can recover if a callback, capability rule, or data migration behaves unexpectedly.

  1. Test the happy path while logged in with the intended role.
  2. Test the same request with a role that lacks the required capability.
  3. Remove the nonce and confirm that no state change occurs.
  4. Change one character in the action or token and confirm rejection.
  5. Retry with an expired or stale page and verify that the client receives a recoverable error.
  6. Log out or switch sessions and confirm that old page tokens are not accepted for the new session.
  7. For REST, test both the presence and absence of the X-WP-Nonce header and verify the endpoint’s permission response.
  8. For guest actions, test separate anonymous sessions and confirm that the additional session mechanism is enforced.

The practical rule is simple: use an action-specific nonce to reduce CSRF risk, verify it in the correct request context, and then make an independent authorization decision. That separation keeps a valid token from becoming a back door to privileged data or operations.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.