WordPress Application Passwords: Setup and Safe Scoping

A credential card with a masked password row and a circular rotation-arrow badge, representing a WordPress application password scoped to one account and rotated independently

Written by

in

A WordPress application password is a 24-character credential, generated from a user’s own profile page, that lets an external tool authenticate to the REST API without ever touching that user’s real login password. Setup takes about two minutes: open Users → Profile, scroll to Application Passwords, type a name for the integration, and click Add New Application Password. WordPress shows the password once, in full – copy it immediately, because only a hash is kept afterward. The part most setup guides skip is the limitation that actually matters: the password inherits the full role of the account that created it. There is no dial in WordPress core to hand out, say, publish-only access. You scope by account, not by password, and that single fact should decide how you set this up before you generate anything.

We use application passwords every day. The agent that drafts and publishes articles on this site, including this one, authenticates to WordPress the same way described below – a dedicated account, a password that lives outside the repository, and a role that has already told us, more than once, exactly what it can’t do.

What application passwords are, and the two-minute setup

Application Passwords became a WordPress core feature in version 5.6, released December 2020. Before that, connecting an external script to the REST API generally meant sending a user’s real login password over Basic Authentication on every request – one credential, reused everywhere, with no way to revoke a single integration without changing the login for everything else too.

The setup itself is short. Log in as the account the integration should act as, go to Users → Profile, and scroll to Application Passwords. Enter a descriptive name for what’s connecting – the name is a label for your own reference, not a permission – and click Add New Application Password. WordPress generates a 24-character string and displays it exactly once; only a hash is stored afterward, so if you lose it, the fix is to revoke that entry and generate a new one, not to go looking for it.

A single account can hold several named application passwords at once, each tracked and revocable independently of the others and of the account’s normal login. WP-CLI exposes the same lifecycle from the command line, with a full wp user application-password command family: create, list, get, delete, exists for idempotent scripting, and record-usage.

The role-inheritance limitation nobody mentions

Here’s the part that catches people who set this up expecting fine-grained scopes: an application password carries the exact same capabilities as the WordPress user account that generated it. WordPress’s own developer documentation states it plainly – authenticating via an application password results in the same capabilities the user has who created it. There’s no field in the creation form for “read-only,” no checkbox for “posts but not settings,” no expiration date, no IP allowlist. The password is a second front door onto the same account. If that account is an administrator, the password can install plugins, add users, and change site settings, exactly like logging in with the real password would.

WordPress core offers two developer-facing filters for site owners who want to restrict the feature itself, rather than an individual password: wp_is_application_passwords_available can turn the feature off entirely, and wp_is_application_passwords_available_for_user can restrict which roles or users are allowed to generate one at all. Neither one lets you take an already-issued password and trim what it can do after the fact. The scoping decision happens before you click “Add New Application Password,” at the account level – not after.

One thing this limitation does not affect: two-factor authentication. Application password requests bypass the 2FA prompt specifically for that authenticated call, which means a human login can stay behind 2FA while a separate application password handles unattended API access – two different authentication paths on the same account, each doing its own job.

Creating a scoped operator user instead of using admin

Since the password can’t be scoped down after the fact, the actual scoping tool is the account you generate it from. WordPress’s own guidance is direct about this: create a dedicated user for the integration if at all possible, rather than issuing the password from an existing admin account. A deploy script, a content pipeline, or an analytics puller each gets its own login, with the lowest built-in role that still lets it do the job – Author if it only manages its own posts, Editor if it needs to touch other users’ content. None of them need Administrator, and most integrations never should have it.

This isn’t a theoretical best practice for us – it’s how our own publishing pipeline is wired. Our site’s REST integration authenticates as a dedicated, non-admin account. That account’s role can create, edit, and publish posts and update page-level SEO fields through the REST API. It cannot purge a caching plugin’s sitemap cache, because that action requires the manage_options capability the account was never given – the request comes back as an HTTP 403 rest_forbidden error, every time, not a partial success. That’s the scoping decision doing exactly what it’s supposed to do: the integration can publish content and structurally cannot touch site-wide settings, no matter what instruction it’s given. A role that was never granted a capability is a wall a script can’t talk its way past.

Rotation and revocation practice

Because each application password is tracked and revoked independently, rotating one doesn’t require touching the account’s main password or any other integration’s credential. From Users → Profile, each entry shows its name and revokes with a single click; from the command line, wp user application-password delete removes one by its UUID, and accepts a comma-separated list for clearing several at once.

A practical rotation habit: name each password specifically enough that a stale one is obvious months later – “content-pipeline-2026” tells you more at a glance than “integration” does – and revoke and reissue immediately whenever a credential might have been exposed: a leaked log, a shared screen, a laptop that changed hands. Because revoking one password has no effect on any other password or the account’s real login, rotation carries none of the “did I just break every other connected tool” risk that comes with changing a shared account password.

Using them safely with agents and CI

An application password used by an autonomous agent or a CI pipeline needs the same two rules that apply to any secret: it doesn’t live in code, and it doesn’t get more access than the job requires. In practice that means the credential is read from an environment variable or a secrets manager at runtime, never hardcoded in a script or committed to version control – our own publishing scripts read theirs from an environment variable set outside the repository, and the repository’s own ignore rules keep it from ever landing in git history by accident.

The account-scoping question from earlier applies with more force once an agent is making the calls, not a human clicking a button. We’ve written in more detail about how we think about access tiers for an AI SEO agent and about the specific gated-approval setup behind the Claude-based agent that runs this pipeline – the application password is the mechanism underneath both, but the account it’s issued from, and what that account structurally cannot do, is the actual safety boundary. If you’re weighing what a WordPress-connected agent should be able to touch at all, start with what the agent is and isn’t before deciding what role to create the password under, and if you want a sense of what unattended API access actually generates in server logs once it’s running, our notes on reading crawler and bot traffic cover the adjacent monitoring side of the same access question.

Frequently asked questions

Do application passwords let you restrict what an integration can access?

Not directly. An application password inherits the full role and capabilities of the WordPress user account that generated it – there’s no per-password scope, expiration, or IP restriction in WordPress core. The only way to limit access is to generate the password from a dedicated account that already holds a lower role, before you create the credential.

How do you set up a WordPress application password?

Log in as the account the integration should use, go to Users → Profile, scroll to Application Passwords, enter a name for the integration, and click Add New Application Password. WordPress displays the 24-character password once – copy it immediately, since only a hash is stored afterward and it can’t be viewed again.

Can you revoke one application password without affecting others?

Yes. Each application password is tracked and revoked independently, both from the profile page’s one-click revoke and from WP-CLI’s wp user application-password delete command. Revoking one has no effect on the account’s other application passwords or on its normal login password.

Does an application password require HTTPS?

Yes. WordPress requires the site to be correctly configured for HTTPS before it will make the Application Passwords feature available; on a site it doesn’t detect as HTTPS, the feature is disabled by default.


About the author: Shivaa Tripathi leads digital and performance marketing at Exotel, focused on demand generation, martech, and applying AI to SEO. He built organic-os, the AI SEO agent that authenticates to this site through the same kind of scoped WordPress application password described above, and runs it in production here.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *