WordPress Application Passwords: Fix 401 Errors on API Calls
If a Zapier flow, a mobile app, or a custom script talks to your WordPress site over the REST API and suddenly starts throwing 401 errors, the culprit usually isn't your plugin - it's Application Passwords and a server that's quietly eating the Authorization header. Here's what's actually happening and how to fix it for good.
What Application Passwords actually are
Since WordPress 5.6, every user account can generate one or more Application Passwords from Users → Profile → Application Passwords. Each one is a random 24-character string tied to a name you choose ("Zapier", "Mobile App", "Make.com Webhook") and works with HTTP Basic Auth against the REST API - no OAuth server, no plugin required.
That's different from your normal wp-admin login, and different from an API-key plugin. A few things worth knowing before you generate one:
- They only authenticate REST API requests (
/wp-json/...), not the wp-admin dashboard itself. - Each password can be revoked individually without touching the user's real login password.
- They're shown in plain text exactly once at creation - copy them immediately, WordPress never displays them again.
- They inherit the full permissions of the WordPress user they belong to, so a password created under an Administrator account can do anything that user can.
Creating one (the part that usually works fine)
- Log in to
wp-adminand go to Users → Profile (or edit any user if you're an admin). - Scroll to Application Passwords near the bottom.
- Type a descriptive name and click Add New Application Password.
- Copy the generated password immediately - it's formatted with spaces like
abcd 1234 efgh 5678 ijkl 9012, but the spaces are cosmetic and can be included or stripped.
The integration then sends requests with an Authorization: Basic header built from username:application_password, base64-encoded. Most plugins, Zapier's WordPress connector, and tools like Postman handle the encoding for you.
Symptom: everything works in Postman, fails on your live site
This is the pattern that sends people down the wrong rabbit hole. You generate the password, test it locally or in Postman, get a clean 200 OK - then wire it into the real integration and get:
{"code":"rest_not_logged_in","message":"You are not currently logged in.","data":{"status":401}}
or sometimes the blunter:
{"code":"application_passwords_not_available","message":"Sorry, Application Passwords are not available for your account.","data":{"status":501}}
Cause 1: Apache/PHP is stripping the Authorization header
This is the most common cause by far on cPanel and other Apache + PHP-FPM/CGI setups. PHP running as CGI or FastCGI (the default on most shared cPanel hosting) doesn't pass the Authorization header through to your script unless you explicitly tell Apache to. WordPress never even sees the credentials, so it treats the request as anonymous and rejects it with a 401.
Fix: add this to your site's .htaccess, above the WordPress block that starts with # BEGIN WordPress:
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [E=HTTP_AUTHORIZATION:%1]
On cPanel this is safe to add through File Manager or via SSH. If your host runs PHP as an Apache module (mod_php) instead of FPM/CGI, this step usually isn't needed - the header passes through natively. Check under MultiPHP Manager in cPanel to confirm which handler is active.
Cause 2: Nginx is dropping it too
If you're on a VPS running Nginx with PHP-FPM (a common LEMP setup), the same header can vanish before it reaches PHP. Add this inside your location ~ \.php$ block:
fastcgi_param HTTP_AUTHORIZATION $http_authorization;
Then reload Nginx:
sudo nginx -t && sudo systemctl reload nginx
Cause 3: Application Passwords is disabled site-wide
The 501 application_passwords_not_available error means the feature itself is turned off, not misconfigured. That happens when:
- A security plugin (Wordfence, iThemes Security, Solid Security) explicitly disables Application Passwords under its hardening settings.
- Your site is running over plain HTTP instead of HTTPS - WordPress disables the feature by default on non-SSL sites unless
WP_ENVIRONMENT_TYPEis set tolocal. - A
wp_is_application_passwords_availablefilter has been added by a theme or plugin to hard-disable it.
Fix: confirm your site loads over HTTPS everywhere (check for mixed-content warnings first), then check your security plugin's settings for an "Application Passwords" or "REST API" toggle. If nothing there explains it, search your theme's functions.php and any custom "must-use" plugins for that filter name.
Cause 4: The password was regenerated or revoked
Application Passwords don't expire on a timer, but they're tied to the exact string generated. If someone on your team clicked "Revoke" while cleaning up unused entries, or the WordPress user's real account password was reset (which some security plugins force-revoke Application Passwords alongside), every integration using that password breaks silently until someone notices the missing webhook data.
Fix: generate a fresh Application Password under the same user, update the integration's stored credential, and label the new one clearly so it isn't mistaken for a stale entry next cleanup.
Quick reference: what causes which error
| Error / status | Most likely cause | Where to look |
|---|---|---|
| 401 rest_not_logged_in | Authorization header stripped by server | .htaccess / Nginx config |
| 501 application_passwords_not_available | Feature disabled or site not on HTTPS | Security plugin settings, SSL status |
| 403 rest_cannot_view / rest_forbidden | User account lacks the required role/capability | Users → the account's role |
| 401 with correct password, works once then fails | Password was revoked or regenerated | Users → Profile → Application Passwords list |
Confirming the fix worked
Test with curl before touching the real integration again, so you know exactly which layer fixed it:
curl -u "username:abcd1234efgh5678ijkl9012" https://yourdomain.com/wp-json/wp/v2/users/me
A working setup returns your user object as JSON. If you still get a 401 after the .htaccess or Nginx change, clear any page cache or object cache in front of the site (LiteSpeed Cache and some CDNs cache based on headers) and retest with a hard refresh or a cache-busting query string.
Prevention: keeping this from breaking again
- Create a dedicated WordPress user for each integration instead of reusing your main admin account - it makes revoking one integration's access trivial without disrupting others.
- Name Application Passwords after the exact integration and date, e.g. "Zapier - Order Sync - 2026-01", so a stale entry is obvious months later.
- Keep a note in your server documentation that the Authorization-header rewrite rule in
.htaccessis required - it's easy for someone to "clean up" the .htaccess file later and remove a rule that looks unfamiliar. - If you migrate hosting (cPanel to VPS, or between VPS providers), re-test every REST API integration - the header-passing behavior depends on the PHP handler, and that's exactly the kind of setting that changes silently during a migration.
If you've checked all of the above and requests still come back unauthenticated, it's worth ruling out a WAF or security layer sitting in front of the server (Cloudflare, Imunify360, ModSecurity) stripping the header before it even reaches Apache or Nginx - test with the WAF paused or in a permissive mode to isolate it.
Frequently asked questions
Do Application Passwords let someone log in to wp-admin?
No. They only authenticate REST API requests (anything under /wp-json/). They can't be used on the normal wp-admin login form, so they don't replace your account password for dashboard access.
Why did my Application Password work in Postman but not in my live integration?
Postman sends requests directly, but your server may still be stripping the Authorization header for requests coming through your integration's usual path. Test with curl from the command line first to confirm whether the header is reaching WordPress at all.
Is it safe to use Application Passwords over HTTP instead of HTTPS?
WordPress disables the feature entirely on non-HTTPS sites by default, and for good reason: Basic Auth credentials travel in a reversible, base64-encoded form, not encrypted. Always use HTTPS with Application Passwords.
Can I limit what an Application Password is allowed to do?
Not per-password out of the box - permissions come from the WordPress user account it belongs to. If you need tighter scoping, create a separate low-privilege user (e.g. Author or a custom role) just for that integration.
I added the .htaccess rewrite rule but I'm still getting 401 errors. What else could it be?
Check for a caching layer (LiteSpeed Cache, Cloudflare, a page cache plugin) serving a cached response before the header is evaluated, and confirm your PHP handler in cPanel's MultiPHP Manager - if it's already running as mod_php, the rewrite rule isn't the fix you need and the cause is elsewhere, like a security plugin restriction.