You have hidden a menu item from everyone except members. Or built a downloads area, set up a client’s editor account, restricted a page to logged-in users. It works when you look at it. The trouble is that you are looking as an administrator, and an administrator sees everything, which makes you the one person on the site who cannot tell whether it worked.

This is the most common way a restriction quietly fails. The page looks locked from where you are sitting, the client emails a week later to say their customer read it anyway, and the page turns out to have been hidden from a menu rather than protected.

By the end of this you will have a reliable way to see the site as each role sees it, a list of the things worth checking, and a clear sense of the difference between hidden and genuinely blocked. That difference is where the real bugs live.

Before you start

You need an administrator account and the ability to create users. If you are working on a client’s live site, tell them before you add accounts, because a new administrator or editor appearing without warning looks exactly like a compromise.

Do this on staging if you have one. A staging site is a private copy of the live site, and most decent hosts will make you one in a couple of clicks. Testing restrictions means submitting forms, triggering emails and occasionally deleting things, and you would rather discover that the members-only form emails the whole customer list on a copy.

If you do create test users on a live site, decide up front how you will remove them, and use a password manager to generate a real password for each. A live site with an account called test and the password test123 is a live site with a back door, and it will outlive the reason you created it.

Why the obvious methods mislead you

Three things people try first. Each is useful for something, and none answers the question you are asking.

A private window logs you out. That is the only thing it does. It shows the logged-out visitor view, which is worth checking, but says nothing about what a subscriber, a customer or an editor sees. If your restriction is “logged in versus not”, it is a fine test. If it is “which role”, it is no test at all.

Logging out and back in works, and it is exhausting. Every template change means logging out, logging in as the test user, checking, logging out, logging back in as yourself. Ten minutes of that and you start assuming things look right rather than checking. Two-factor prompts and autofill slow it further, so you cut corners on the account you most need to verify.

A second browser or browser profile is the best of the three, because you can be logged in as both people at once and flip between windows. It solves the tedium, not the underlying requirement, which is that you still need a real second account with the right role before you have anything to log into.

So the question is not which browser to use. It is how to see each role accurately without turning a five second check into a five minute ritual.

Step 1: Decide what you are actually testing

Before you create anything, write down what “correct” looks like for that role. It comes down to four things.

Admin menu visibility. Which menu items should be in the sidebar, and whether the admin bar shows anything it should not. This is the one clients notice.

Restricted content. The members page, the private post, the category that should only appear to subscribers, the custom field that should only show to editors.

Forms and actions. Can they submit the form, does it succeed, do the restricted fields appear, and what happens when they try something they should not. A form that silently fails is a support ticket. A form that succeeds when it should not is a bigger problem.

Hidden versus blocked. For everything above, ask what happens if the user goes straight to the URL. This is the check people skip.

That last one deserves spelling out. Removing a page from a menu hides it. Wrapping content in an is_user_logged_in() check hides it in one template. Neither stops anyone loading the URL, and neither keeps the content out of search results, the RSS feed, the site’s own search box, or the REST API. That last one is worth knowing about: every WordPress site hands out its content as raw data at addresses beginning /wp-json/, which is how apps and the block editor read it, and you can see yours right now by visiting /wp-json/wp/v2/posts in a browser. If something genuinely must not be read by the wrong person, the protection has to live where the content is served, not where it is displayed. Otherwise you have built an inconvenience rather than a restriction, and I have been called in to fix sites where somebody other than the owner found the difference first.

Step 2: Create a real test account for each role

This is the most accurate method there is, and for anything that matters it is the one to use. A real account goes through the same login, the same capability lookups and the same plugin logic as a real user, because it is one. A capability is a single permission, like “can publish posts” or “can delete other people’s pages”, and a role is just a named bundle of them. Editor and Subscriber are bundles.

Create one account per role you need to check. In the admin that is Users, then Add New. If you have WP-CLI, the command line version of WordPress that many hosts offer, this is quicker. Skip the block if you do not, since the admin screen does exactly the same job.

# One account per role, with a generated password printed to the terminal.
wp user create test-subscriber you+test-sub@example.com --role=subscriber
wp user create test-editor you+test-ed@example.com --role=editor

A few things that make this survivable:

  • Name them obviously. test-editor beats sarah2. In six months you want to look at the users list and know instantly which accounts are yours.
  • Use plus addressing so every test account has a real inbox you control. On most mail providers, including Gmail, Outlook, Fastmail and iCloud, anything after a + in an address is ignored on delivery, so mail to you+test-sub@example.com lands in your normal inbox. You will need this, because half of what you are testing sends email.
  • Generate the passwords. Let WordPress or your password manager do it, and store them. Never a password you reuse, and never anything with “test” in it.
  • Remember they are real accounts. They show up in author archives, in any member directory the site has, and, once they have published anything, in the site’s user data at /wp-json/wp/v2/users. On a live site, every account that exists is one more door somebody could try from the moment you create it.

When you are done, remove them. Deleting a user asks whether to attribute their content to someone else, so decide that deliberately rather than clicking through. On multisite, removing a user from a site and deleting them from the network are different actions, and the first is usually what you want.

If you cannot delete them yet, demote them to subscriber and change the password. An abandoned test editor account is one of the more boring ways a site gets edited by someone who should not be.

Step 3: Keep both logged in with a second browser profile

Once the accounts exist, stop logging in and out. Use a second browser, or a second profile in the same browser, and stay signed in as yourself in one and as the test user in the other. Two windows side by side, refresh both after a change, and the loop goes from a minute to a second.

Profiles beat private windows here because the session survives. You can leave the test user signed in for days, which matters when you are working through a long list of restricted pages.

The limit is arithmetic. Six roles means six profiles or six rounds of logging in, with any two-factor prompt that implies.

Step 4: Check the logic directly, in code

Sometimes the fastest answer is not to look at the page at all, but to ask WordPress the question outright. This section needs WP-CLI and a terminal, so it is the one part of this article that is properly developer territory. Take this route when the behaviour is confusing rather than obviously wrong, because it separates “the permission check is wrong” from “the template is wrong”. If you have no terminal, the same answers can be had from a real test account and a careful look at the page, it just takes longer.

# Everything this user can do, role capabilities and individual grants.
wp user list-caps test-editor

# The precise question, about the precise user.
wp eval 'var_dump( user_can( 12, "edit_others_posts" ) );'

# Run something as that user, so current_user_can() answers for them.
wp --user=test-editor eval 'var_dump( current_user_can( "edit_post", 45 ) );'

That last one is the useful trick. current_user_can() is the function your theme uses to ask “is the person looking at this allowed to do X?”, and it needs somebody to be logged in before it can answer. The --user flag tells WP-CLI to pretend that person is logged in, so you can run exactly the check your template is making without touching a browser.

If the capability check says the user is not allowed but the page still shows the content, the check is not the problem. Your template is asking a different question, or asking it after the content has been output. If it says they are allowed and you expected otherwise, look for a capability granted directly on the user record, or a plugin filtering user_has_cap. There is more on where those grants come from in my piece on WordPress user roles and capabilities.

The fast loop: a role switcher

The manual routes above are correct and slow, and slow is what makes people stop checking. When I am iterating on a template, I do not want to alt-tab into a second profile forty times.

That is what I built ABCode View As Role Switcher for, free on wordpress.org. Pick a role from the toolbar and the front end reloads as that role sees it.

  • Covers every role, and the logged-out guest view, with no second browser or second account.
  • A genuine capability switch, not a cosmetic preview, so conditional logic in your theme and plugins evaluates as it would for that user.
  • Sessions expire on their own after 15 minutes, 1 hour or 8 hours, so you cannot forget you are in one.
  • Nothing is written to the database, and no stored roles are touched.

The limits decide when to use it. It switches by role, not by person, so anything tied to one individual, their orders, their membership status, capabilities granted to them directly, still needs their account or a test account that mirrors it. It is a front-end tool, so admin screen checks want a real login, and so does the final sign-off confirming the members area really is private, because a real session is what your visitors get. It needs an administrator account, so it is no help to a remote client asking why a button is missing. Before that final pass, restricting a menu, hiding a field, building out a members area, it turns twenty checks in a row into two clicks and a reload each instead of a log out and a log back in. That is where it pays for itself.

How to check it worked

Take the restricted page and try it four ways: as an administrator, as the role that should have access, as a role that should not, and logged out entirely.

For the role that should not have access, do not stop at “the link is gone”. Paste the URL in directly. What you want back is a redirect somewhere else, a 403 (“you are not allowed to see this”) or a 404 (“there is nothing here”). If you get the content, it was never restricted.

Then check the side doors for anything confidential. Search the site’s own search box for a phrase from the page. Load /wp-json/wp/v2/posts and /feed/ while logged out and see whether the title or excerpt appears. Search engines find these before people do.

When it does not work

The restricted page still shows content

Page caching. Caching means storing a finished copy of a page and handing that to the next person instead of building it again. If a copy made for one visitor is being served to another, that is both a broken test and a genuine leak. Confirm it by adding something like ?nocache=1 to the end of the URL, which most caches treat as a page they have not seen and so build fresh. Then check that your caching plugin, and any cache your host or CDN runs in front of the site, skips logged-in users and never stores restricted URLs at all.

You still see everything as the test user

Two accounts logged in to the same browser profile, or a page rendered before you switched. Hard refresh, and check the greeting in the toolbar rather than the tab you think you are in.

The link is hidden but the URL still works

The most common outcome of all. Hiding a menu item, or wrapping output in a template condition, does not protect the underlying content. The fix belongs where the content is served, before a single line of the page is sent. In code that means template_redirect, which fires early enough to turn the visitor away, for whole pages, a permission check inside the code that handles anything submitted, and pre_get_posts or a membership plugin to keep the content out of listings and feeds. If you are not writing the code yourself, a decent membership or content restriction plugin does all three, which is the right answer for most sites.

The test account behaves differently from the client’s real account

Almost always an individual capability grant on their user record, a second role, or a membership plugin keyed to their subscription rather than their role. wp user list-caps on both accounts shows the difference in seconds.

A form works for you and fails for them

The code behind the form is checking a capability the role does not have, or the nonce is being generated somewhere that user never reaches. A nonce is a short one-off token WordPress puts in a form to prove the submission came from the right person on the right screen, and if the user cannot load the screen that issues it, the submission is rejected. Watch what the server sends back rather than what the page shows, and switch on debug logging so the failure arrives with a message attached instead of silently.

Common questions

Can I log in as another user without knowing their password?

Yes, with a plugin built for it. There are long-standing options that let an administrator switch into a specific user account and back again, User Switching being the best known. That is the right tool when the question is about one particular person, a customer whose order history is behaving oddly, rather than a role in general. It is an administrator-level power, so treat installing it on a client site as a decision worth mentioning.

Is a private window enough?

Only for the logged-out view. Useful for that, and useless for anything role-specific, because it does not log you in as anybody.

Should I test on the live site or on staging?

Staging for anything that writes, sends email or takes payment. Live for a final read-only confirmation after deployment, since staging and live differ in ways that matter, particularly caching and hosting-level access rules.

How many test accounts do I actually need?

One per role a real person will hold. If nobody is ever going to be a contributor, do not create a contributor. Two or three is normal.

Getting the check down to a few seconds

Restrictions ship broken not because people do not care, but because checking them properly is tedious enough to skip, and an administrator’s view of the site looks convincingly correct. Anything that makes the check take seconds rather than minutes gets done every time, and that matters more than which method you pick.

So: real test accounts for the things that count, a second browser profile so you are not logging in and out all day, a capability check in the terminal when the behaviour makes no sense, and a role switch for the fast loop while you are still changing code. Whatever route you take, finish by pasting the restricted URL in directly as somebody who should not have it. Hidden and blocked are not the same thing, and only one is a restriction.

If you are building something where that difference has consequences, a members area, a client portal, a site where the wrong person seeing the wrong page is a real problem, it is worth having the permission logic written deliberately rather than assembled from settings screens. That is the sort of thing I do as custom plugin work, and you are welcome to get in touch if you would rather not find out the hard way.