Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To keep password-protected posts out of WordPress home pages and archives, either add has_password => false to a custom WP_Query, or use the documented pre_get_posts plus posts_where pattern for eligible front-end queries. The global pattern excludes protected posts from those lists while preserving pagination, but it does not make the posts private or block direct access.

Choose the right method

Situation Recommended method Scope
The homepage, archive, or another main front-end query should omit protected posts Scoped pre_get_posts and posts_where filter Eligible front-end queries across the site
You control a secondary loop or custom query has_password => false Only that query
A Query Loop block supplies the list Check the block settings; use a custom query or carefully scoped code if password status is unavailable Depends on the block and theme implementation

Hide protected posts from the main front-end loop

WordPress documents a filter that adds an empty-password condition to front-end SQL. Put the code in a small custom plugin rather than a parent theme file so a theme update does not remove it. The official guidance is to avoid applying it to single posts, pages, and administration screens.

Create a PHP file in wp-content/plugins/, add a plugin header, and activate it from Plugins in the dashboard:

<?php
/**
 * Plugin Name: Hide Password-Protected Posts from Lists
 */

function itg_hide_protected_posts_from_lists( $query ) {
    if ( is_admin() || is_single() || is_page() ) {
        return;
    }

    add_filter( 'posts_where', 'itg_exclude_password_protected_posts' );
}
add_action( 'pre_get_posts', 'itg_hide_protected_posts_from_lists' );

function itg_exclude_password_protected_posts( $where ) {
    global $wpdb;

    return $where . " AND {$wpdb->posts}.post_password = ''";
}

The condition keeps rows whose post_password value is empty. WordPress says this documented approach removes protected posts from the targeted lists without affecting pagination. The source example is a starting point: if your site has several custom queries, narrow the condition further so unrelated front-end queries are not changed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

After activation, test the actual homepage and archive URLs while logged out and logged in. Confirm that ordinary posts still paginate correctly and that a protected post no longer appears in the list.

Exclude protected posts from one custom query

For a secondary loop that you control, keep the rule local by adding the documented has_password argument:

$public_posts = new WP_Query( array(
    'post_type'      => 'post',
    'posts_per_page' => 10,
    'has_password'   => false,
) );

has_password => false selects posts without passwords. Use true to select only protected posts, or null to allow both kinds. This is preferable to a global filter when a theme widget, shortcode, or plugin list is the only place that needs the exclusion.

What to do with Query Loop blocks

The documented Query Loop block controls include category and tag filters and an option to exclude the current post, but the cited documentation does not describe a built-in password-status filter. If the editor does not expose the condition you need, use a custom query/block implementation or carefully scoped PHP, then validate the result against your WordPress version and theme.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why a hidden loop item is not private content

Password protection controls access to post content; it does not necessarily hide the title or password prompt. Private visibility is a separate WordPress setting intended for users with the appropriate roles. Removing a post from one loop changes that query’s listing only. It does not promise to remove the post from every feed, REST/API response, metadata view, media URL, search implementation, or direct URL.

If a template prints custom fields beside a post, check the password state before outputting sensitive values. WordPress specifically recommends using post_password_required() when deciding whether protected content or custom-field data should be displayed.

if ( ! post_password_required() ) {
    echo esc_html( get_post_meta( get_the_ID(), 'internal_note', true ) );
}
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot posts that still appear

  • Identify the query: the visible list may be a secondary WP_Query, a widget, a shortcode, or a block rather than the main query.
  • Use a local argument when possible: add has_password => false to a custom query you control.
  • Check query scope: the global example intentionally leaves single posts, pages, and admin requests alone.
  • Inspect plugin and theme code: a query builder may replace or modify the SQL after your filter runs.
  • Clear caches and retest: page, object, and CDN caches can keep an old list visible.
  • Test all relevant surfaces: homepage, category and date archives, search, feeds, and any custom listing may use different queries.

For the documented behavior and syntax, see WordPress’s password-protection guide and the WP_Query developer reference. The Query Loop block documentation describes its available editor filters, while WordPress’s content-visibility guide explains the distinction between password-protected and private content.

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.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.