What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use an action-specific WordPress nonce to reduce CSRF risk on a state-changing request, verify it in the context that received it, and still enforce permissions with a capability check. A nonce confirms that WordPress generated the page or script; it does not authenticate the requester or authorize the operation.
Antihost offers managed WordPress hosting with free migration, one-click staging and a 14-day free trial.
What a WordPress nonce does
WordPress uses the term “nonce” for a hash-based value that helps protect forms, URLs, AJAX calls, and cookie-authenticated REST requests from cross-site request forgery (CSRF). The name comes from “number used once,” but a WordPress nonce is not necessarily numeric and is not single-use. It remains valid for a time window and can normally be submitted more than once during that window.
As an Amazon Associate I earn from qualifying purchases.
The useful question is whether the request came from a page or script that WordPress generated for the current user and action. That is different from asking who the user is or whether the user may perform the operation. Authentication, authorization, and input validation remain separate controls.
Choose an action string first
Every nonce should be tied to a precise action. Use a context-rich value such as delete-comment_123, not a generic string such as save or my-plugin. Include the operation and, where practical, the object identifier or other context that distinguishes one dangerous action from another.
#1 Best Overall
- Specific:
delete-comment_123identifies deletion of comment 123. - Stable: use exactly the same action when creating and verifying the token.
- Scoped: do not reuse a token intended for one operation on unrelated operations.
An action string is not a permission. A user who presents a valid token can still fail the capability check for the target resource.
Creating nonces for forms
Use wp_nonce_field() inside a form
For an HTML form, call wp_nonce_field() while rendering the form. It prints hidden fields containing the nonce and its field name, allowing the submitted request to carry the value back to WordPress.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minute<form method='post' action='<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>'>
<input type='hidden' name='action' value='delete_comment'>
<input type='hidden' name='comment_id' value='<?php echo esc_attr( $comment_id ); ?>'>
<?php wp_nonce_field( 'delete-comment_' . $comment_id ); ?>
<button type='submit'>Delete comment</button>
</form>
The action passed to wp_nonce_field() must match the action used during verification. Escape any separately rendered IDs and values as appropriate for their output context; the nonce does not sanitize the rest of the form.
When a custom field name is useful
The function can use a custom nonce field name when your handler expects one. If you change the name, pass that same name to the verification function or read it deliberately in custom handling. Keeping the default field name is usually simplest and makes WordPress conventions easier to recognize.
Creating nonces for links and URLs
Use wp_nonce_url() for a nonce-bearing URL
For a link that triggers a state-changing action, pass the destination URL and action to wp_nonce_url(). WordPress adds a nonce query parameter, normally named _wpnonce.
Rank #2
<?php
$url = add_query_arg(
array(
'action' => 'delete_comment',
'comment_id' => $comment_id,
),
admin_url( 'admin-post.php' )
);
$protected_url = wp_nonce_url( $url, 'delete-comment_' . $comment_id );
?>
<a href='<?php echo esc_url( $protected_url ); ?>'>Delete comment</a>
Nonce-protecting a URL does not make a destructive action safe to perform with a simple GET request. For operations that change data, prefer a POST request and verify the nonce in the handler. A nonce on a link is appropriate when an administrative flow intentionally uses a protected URL and the server-side handler still checks permissions.
Verifying admin forms and URLs
Use check_admin_referer() in the matching handler
For an admin form or admin URL, call check_admin_referer() with the same action string used to create the nonce.
<?php
check_admin_referer( 'delete-comment_' . $comment_id );
if ( ! current_user_can( 'moderate_comments' ) ) {
wp_die( 'You are not allowed to delete comments.' );
}
$comment_id = absint( $_POST['comment_id'] ?? 0 );
// Validate that the ID is present and that the requested comment is the intended target.
// Perform the deletion only after validation and the capability check.
?>
With normal settings, failed verification stops the request and displays an error rather than allowing the operation to continue. Verify before changing data, sending email, charging a customer, or performing any other side effect.
Do not confuse a referer check with authorization
check_admin_referer() verifies the nonce and, in the relevant WordPress flow, the request context. It does not prove that the current account may edit the selected post, delete the selected comment, or administer the plugin. Check the capability that maps to the resource and operation immediately before performing the action.
Verifying AJAX requests
Generate and expose the token
Create a nonce with wp_create_nonce() and make it available to the JavaScript that sends the request. A common approach is localizing script data or using an inline configuration object.
Free tools Windows power users keep installed
One-click scans. No signup required.
<?php
$settings = array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'delete-comment_' . $comment_id ),
);
wp_localize_script( 'my-plugin-script', 'MyPlugin', $settings );
?>
The browser then includes the nonce in the request, commonly in a field named _ajax_nonce or another name that the handler specifies.
fetch(MyPlugin.ajaxUrl, {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
body: new URLSearchParams({
action: 'delete_comment',
comment_id: String(commentId),
_ajax_nonce: MyPlugin.nonce
})
});
Verify with check_ajax_referer()
In the AJAX callback, use the same action string and identify the request field if you chose a custom name.
<?php
function my_plugin_delete_comment_ajax() {
check_ajax_referer( 'delete-comment_' . absint( $_POST['comment_id'] ?? 0 ), '_ajax_nonce' );
if ( ! current_user_can( 'moderate_comments' ) ) {
wp_send_json_error( array( 'message' => 'Permission denied.' ), 403 );
}
$comment_id = absint( $_POST['comment_id'] ?? 0 );
if ( ! $comment_id ) {
wp_send_json_error( array( 'message' => 'Invalid comment ID.' ), 400 );
}
// Confirm the comment exists and then perform the validated operation.
wp_send_json_success();
}
add_action( 'wp_ajax_delete_comment', 'my_plugin_delete_comment_ajax' );
?>
check_ajax_referer() returns 1 when the nonce was generated 0–12 hours ago and 2 when it was generated 12–24 hours ago. By default, it terminates the request when verification fails. If your endpoint needs a JSON error envelope or a different recovery path, pass the function’s stop behavior accordingly and handle the failure response yourself; never continue to the protected operation.
Sending a nonce to the WordPress REST API
Cookie-authenticated REST requests from a logged-in session
For REST API requests made inside a WordPress login session, create a nonce with the special action wp_rest. Send it on every manual request in the X-WP-Nonce header. WordPress also accepts the _wpnonce parameter, but the header keeps the token out of the URL.
<?php
$rest_nonce = wp_create_nonce( 'wp_rest' );
?>
<script>
const restNonce = '<?php echo esc_js( $rest_nonce ); ?>';
fetch('/wp-json/wp/v2/posts/123', {
method: 'POST',
headers: {
'X-WP-Nonce': restNonce,
'Content-Type': 'application/json'
},
body: JSON.stringify({title: 'Updated title'})
});
</script>
WordPress’s REST cookie authentication checks the login cookies and the nonce. If the required REST nonce is missing, the request is treated as unauthenticated rather than as an authenticated cookie request. A valid REST nonce still does not grant permission to edit post 123; the endpoint’s capability checks decide that.
Rank #4
Application passwords are separate
Cookie-based REST authentication is intended for requests made within the WordPress session. Application passwords, available since WordPress 5.6, are a separate authentication option for clients that are not operating inside that browser session. Do not send a cookie-session nonce as a substitute for credentials required by an external integration.
Nonce lifetime and session behavior
The default window is variable
WordPress’s default nonce setting is one day, implemented as two half-life ticks. In practice, a nonce is valid for a variable period between 12 and 24 hours, depending on when during the tick cycle it was created. The age values returned by check_ajax_referer() reflect the same two ranges: 1 for 0–12 hours and 2 for 12–24 hours.
Treat the token as time-limited, not as a one-request credential. If your application requires a shorter or independently managed lifetime, design that policy explicitly rather than assuming the default behaves like a strict 24-hour timer.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Login and logout can invalidate rendered tokens
Nonces are tied to the current user session. If a user logs in or out asynchronously, a nonce already rendered into an open page may no longer verify. Refresh the page or obtain a newly generated token after a session transition instead of retrying indefinitely with the stale value.
Logged-out visitors need an additional mechanism
For visitors who are not logged in, WordPress normally uses user ID 0 when generating nonces. That means all anonymous visitors can share the same user context for nonce purposes. If a guest action is important enough to protect individually, add a session mechanism through the nonce_user_logged_out filter and bind the action to that guest session. A public nonce alone is not an adequate identity or abuse-prevention system.
Best Value
Nonce security boundaries
A nonce is one layer in a request’s defense. For every state-changing handler, apply the following controls in order:
- Verify the nonce using the function for the request context.
- Authenticate the user or session through WordPress’s normal mechanism.
- Check the precise capability for the operation and target resource with
current_user_can()or an equivalent authorization check. - Validate types, ranges, object ownership, and relationships in submitted data.
- Sanitize data for its destination and escape it when rendering output.
- Perform the side effect only after all checks pass, then return a response appropriate to the caller.
For example, a valid delete-comment_123 nonce does not authorize a subscriber to delete comment 123, does not prove that the submitted comment ID is the one displayed on the page, and does not make an unvalidated text field safe to store.
Which verification function should you use?
| Request context | Create the token | Verify it | Failure behavior and notes |
|---|---|---|---|
| Admin form | wp_nonce_field( $action ) |
check_admin_referer( $action ) |
Normally terminates on failure; keep a separate capability check. |
| Admin or protected URL | wp_nonce_url( $url, $action ) |
check_admin_referer( $action ) |
Prefer POST for data-changing operations; escape the final URL. |
| AJAX | wp_create_nonce( $action ) |
check_ajax_referer( $action ) |
Returns age code 1 or 2 when valid and stops by default when invalid; customize only when you return your own error response. |
| Custom handler | wp_create_nonce( $action ) |
wp_verify_nonce( $value, $action ) |
Returns a validity/age result for your code to interpret; you must decide how to report failure. |
| REST API with login cookies | wp_create_nonce( 'wp_rest' ) |
REST cookie authentication checks the nonce | Send X-WP-Nonce or _wpnonce on each request; missing tokens are treated as unauthenticated. |
Using wp_verify_nonce() for custom handling
Use wp_verify_nonce() when the standard admin or AJAX functions do not fit your response format or transport. Read the submitted value, pass it with the exact action, and stop on a false result.
<?php
$value = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ?? '' ) );
$result = wp_verify_nonce( $value, 'export-report' );
if ( false === $result ) {
wp_send_json_error( array( 'message' => 'The security token is invalid or expired.' ), 403 );
}
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( array( 'message' => 'Permission denied.' ), 403 );
}
// Validate export parameters before generating the report.
?>
Do not use a custom verifier merely to avoid handling errors. The important requirement is that an invalid token cannot reach the protected operation.
Troubleshooting common failures
“Are you sure you want to do this?” or an invalid nonce error
- Confirm that the action string is byte-for-byte identical during creation and verification.
- Check that the submitted field is present and has not been renamed by JavaScript or a proxy.
- Refresh the page if the user recently logged in, logged out, or switched accounts.
- Verify that caching is not serving a page containing another user’s or an expired token. Do not cache personalized nonce-bearing HTML publicly.
AJAX returns an unexpected HTML error page
The default failure behavior of check_ajax_referer() terminates the request. If the browser expects JSON, configure the handler to detect failure and return a JSON error, while preserving the rule that no protected code runs after failure.
REST request becomes unauthenticated
- Generate the token with the action exactly
wp_rest. - Send it as
X-WP-Nonceon every manual cookie-authenticated request, not only the first one. - Make sure the browser is sending the WordPress login cookies and that the page has not retained a token from an earlier session.
- For a non-browser integration, use the authentication method intended for that client rather than relying on a browser-session nonce.
The nonce verifies but the operation is still rejected
That is expected when the current account lacks the required capability, the object does not exist, or submitted data fails validation. Keep those checks; a nonce is not an override for authorization or business rules.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Deployment checklist
Before shipping a plugin or REST change that adds or changes nonce handling:
- Use a staging environment to exercise valid, expired, missing, altered, and cross-action tokens.
- Test both the permitted and forbidden capability paths with different user roles.
- Test after login, logout, and session switching so stale-page behavior is understood.
- Check anonymous flows separately; decide whether user ID 0 is sufficient or whether a guest session is required.
- Confirm that cache layers do not share personalized nonce-bearing pages.
- Back up the site before significant plugin or application changes and keep a rollback path.
- Log failures without recording complete nonce values, since a token should not become a new credential in your logs.
End-to-end pattern
A robust implementation follows one chain: choose a narrowly scoped action, create the token in the page or script, transmit it with the request, verify it in the matching context, check the user’s capability, validate every input, and only then perform the state change. The same pattern applies whether the transport is an admin form, a protected URL, an AJAX request, or a cookie-authenticated REST call; only the creation and verification APIs differ.
Quick Recap
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.




