WordPress user enumeration is any way an outsider can list the login names on your site: /?author=1 redirecting to /author/admin/, the REST API's users endpoint, author archives, and a login form that confirms which usernames exist. To stop it, redirect author scans, restrict the users endpoint to logged-in users and make sure no login is called "admin". A known username is half a password to a brute-force script. This guide closes each leak, most without a plugin, replaces the "admin" account in about ten minutes and adds the two defences that matter more than any hidden name. It is step 4 of the WordPress security checklist.
Quick answer
- Test: open
https://yoursite.com/?author=1. If you land on/author/admin/, the first user's login is almost certainly "admin". - Replace "admin": create a new administrator with a unique username, log in as it, delete "admin" and attribute its content to the new user. WordPress cannot rename a login.
- Close the leaks: redirect
?author=and author archives on a single-author site, remove the users REST routes for visitors, give every author a slug that differs from their login. - Real defence: two-factor login and login rate limiting. A hidden username slows scripts down; it does not stop a determined attacker.
Where WordPress reveals usernames
WordPress gives each user three names: the login (user_login), the slug (user_nicename, made from the login when the account is created) and the display name. Several places show them by design:
| Leak | What it shows | How to close it |
|---|---|---|
/?author=1, 2, 3… | Redirects to /author/<slug>/ for users with published posts | Redirect it (step 4) |
| Author archives and bylines | The slug in every author link | Disable archives or change slugs (steps 3-4) |
/wp-json/wp/v2/users | Slug and display name of every user with published posts | Remove the routes for visitors (step 5) |
oEmbed (/wp-json/oembed/1.0/embed?url=…) | Display name and author archive URL | Change the slug (step 3) |
| Login form errors | "The password you entered for the username admin is incorrect" confirms the name | Generic error message (step 5) |
| Comment markup | A class such as comment-author-admin | Change the slug |
| Core sitemap | Author archives at /wp-sitemap-users-1.xml | Remove the users sitemap (step 4) |
| RSS feed | <dc:creator> with the display name | Set a display name that is not the login |
WordPress treats usernames as public information, so none of this is a bug in its eyes. That is the reason a username should never be the thing that protects the site. The login side, from passwords to two-factor setup, is in WordPress login security.
How getReport checks it
When the page reveals WordPress, the WordPress health check makes one request for this: a HEAD request for /?author=1. It reads where the first redirect points and records the slug only if it is admin or administrator. Any other name is discarded on the spot: never stored, shown or put into the report. getReport does not call the REST API, submit the login form or try other user numbers.

A pass means /?author=1 did not redirect to admin or administrator. It does not prove there is no such user: if user 1 has no published posts, there is nothing to redirect to. Check the user list yourself (step 1).
A broader check for enumeration through the REST API's users endpoint, wp-user-enumeration, is planned for the WordPress Doctor and not live yet. Like the other sensitive WordPress checks, it will show a plain yes or no to anyone who runs the report, and the usernames only to the site's verified owner.
Three findings make a known username more dangerous, because each gives an attacker a second way in:
A public staging copy usually has the same users as the live site with older code, and a readable .env or .git folder can hold the database password itself. Fix those first if they show up.
Step by step
1. List the administrators
Users → All Users → filter by Administrator. Or from a terminal:
wp user list --role=administrator --fields=ID,user_login,user_nicename,display_name,user_emailNote the ID and email of the "admin" account.
2. Replace the "admin" user
Users → Add New User:
- Username: unique, and not your name, your domain or a role ("admin", "editor", "webmaster"). Nobody else needs to see it.
- Email: WordPress requires a unique address. To keep your usual address, first change the old account's email to another one you control (a
+oldalias works with most providers). - Password: a long generated one in a password manager. Role: Administrator.
Log out, log in as the new user and confirm that you can reach Settings and Plugins. Then Users → All Users → hover over "admin" → Delete, choose "Attribute all content to" the new user and confirm. With WP-CLI:
wp user create k7-maintainer you@example.com --role=administrator --display_name="Studio Team"
wp user delete 1 --reassign=5 # 5 = the new user's IDPosts keep their URLs, dates and comments; only the author changes. /?author=1 now answers 404 because user 1 no longer exists.
3. Give every author a slug that is not their login
| Name | Field | Where it shows | Can you change it? |
|---|---|---|---|
| Username | user_login | Login form only | No: "Usernames cannot be changed" |
| Slug | user_nicename | /author/<slug>/, REST API, oEmbed, CSS classes | Not in wp-admin; WP-CLI or a plugin |
| Display name | display_name | Bylines, comments, feeds | Yes, Users → Profile → "Display name publicly as" |
Changing the display name does not change the slug, so a user called k7-maintainer publishes under /author/k7-maintainer/ even as "Studio Team". To decouple them:
wp user update 5 --user_nicename=studio-teamThe old author URL stops working after this, so do it before the archive has links, or redirect the old address.
4. Hide author archives on a single-author site
When one person or team writes everything, author archives duplicate the blog index and mainly reveal the slug. Switch them off:
- Yoast SEO: Yoast SEO → Settings → Advanced → Author archives → turn off "Enable author archives".
- Rank Math: Rank Math → Titles & Meta → Authors → Author Archives → Disabled.
Without an SEO plugin, a must-use plugin does the same and catches ?author= before WordPress's own redirect runs (priority 1 is earlier than core's canonical redirect at 10):
<?php
// wp-content/mu-plugins/no-user-enumeration.php
add_action('template_redirect', function () {
if (is_author() || isset($_GET['author'])) {
wp_safe_redirect(home_url('/'), 301);
exit;
}
}, 1);
// Drop the author list from the core sitemap (/wp-sitemap-users-1.xml).
add_filter('wp_sitemaps_add_provider', function ($provider, $name) {
return $name === 'users' ? false : $provider;
}, 10, 2);On a site with several authors whose archives help readers, keep them and rely on step 3.
5. Close the REST API and the login form
Core has no setting for either. Add these to the same must-use plugin. The first removes the users routes for visitors who are not logged in, so the block editor, which calls them while you are logged in, keeps working. The second replaces the login error that confirms a username with a generic one:
add_filter('rest_endpoints', function ($endpoints) {
if (!is_user_logged_in()) {
unset($endpoints['/wp/v2/users']);
unset($endpoints['/wp/v2/users/(?P<id>[\d]+)']);
}
return $endpoints;
});
add_filter('login_errors', function () {
return 'The username or password is incorrect.';
});Security plugins such as Wordfence and Solid Security have switches for the same jobs if you prefer a settings screen.
6. Add the defences that actually stop attacks
- Two-factor login. The community-maintained Two Factor plugin on wordpress.org adds authenticator-app codes and backup codes. With it, a known username and a guessed password are no longer enough.
- Login rate limiting. Lock out an address after a few failed attempts, at the host or CDN, or with a plugin such as Limit Login Attempts Reloaded.
- XML-RPC. If nothing uses it, block it: it accepts many password guesses in one request. xmlrpc.php: what it is and how to disable it shows how to check first.
Platform notes
Multisite. Super admins are stored by login name in a network setting. Replace one by creating the new user, granting super admin under Network Admin → Users → Edit, logging in as it, then deleting the old one. Never rename one in the database.
Managed WordPress hosts. Some block xmlrpc.php or rate-limit wp-login.php for you. Check before adding plugins that do the same work twice.
Verify
- Re-run the WordPress health check. The finding reads "No default admin author exposed".
- Run
/?author=1through the redirect checker: it should answer 404 or go straight to the home page, with no/author/hop. - In a private window,
/wp-json/wp/v2/usersreturns an error and a wrong password on the login form shows the generic message. - Log in with the new account and its second factor.
Common mistakes
- Renaming the user in the database. Editing
user_loginby SQL leaves the slug asadmin, and one typo can lock everyone out. Create a new user instead. - Deleting "admin" without reassigning content. "Delete all content" deletes every post that user wrote. Restore the backup and delete again with "Attribute all content to".
- Changing only the display name. Bylines change;
/author/admin/stays. - Blocking the whole REST API. The block editor, many plugins and embeds need it. Remove only the users routes, and only for visitors.
- Forgetting the staging copy. It has the same "admin" user. Protect staging with a password, as in the WordPress rookie mistakes, and replace the user there too.
Questions people ask
Can WordPress usernames be kept completely secret?
Not reliably. You can close the author redirect, the REST users endpoint, the sitemap and the login error, but a username can still leak through a theme, a plugin, an old feed or a data breach elsewhere. Treat enumeration fixes as noise reduction, and make the password and a second factor carry the security.
Does removing the users REST endpoint break the block editor?
No, if you remove it only for visitors who are not logged in, as in the snippet above. The block editor calls the users routes as a logged-in user, for example to fill the author dropdown, and those calls keep working. Blocking the endpoint for everyone, or the whole REST API, breaks the editor and many plugins.
Does disabling author archives hurt SEO?
Not on a single-author site. Its author archive repeats the blog index, so it adds a duplicate page rather than rankings. Disable it and redirect it to the home page or blog. On a multi-author site where readers browse by writer, keep the archives and give each author a slug that differs from their login.
Why does /?author=1 not redirect on my site?
Either user 1 no longer exists, user 1 has no published posts, or a plugin or server rule already blocks author scans. None of these proves the site is free of enumeration: check /?author=2 and /wp-json/wp/v2/users in a private window, and look at the user list for a login called admin.