The following snippet is from a sidebar widget that lists "recent posts". Since its on the home page and I feature my lastest sticky post prominently on that page, I want to skip over the sticky in this loop. However, the post_not_in=sticky_posts has no effect.

    $the_query = new WP_Query("showposts=$number&offset=1&order=ASC&post_not_in=sticky_posts");

    while ($the_query->have_posts()) : $the_query->the_post();
        $do_not_duplicate = $post->ID; ?>

4 Answers 4


I took @tnorthcutt's answer from WordPress' Codex on query_posts() about Sticky Parameters and created a tandalone example you can drop as test.php into your website's root and see it run by navigating to a URL like this, with your domain substituted:


Some notes on the code; I had to use an array equivalent of the query string you passed to WP_Query() because the post__no_in argument can't be passed in as a comma delimited string (not sure why, probably an oversight?).

Also I wanted to make sure you know that starting with an offset=1 (instead of offset=0) means you'll be excluding the first post that otherwise would be returned by the query. Of course you'll still get the number of posts specified by $number assuming you have that many applicable posts +1. So here's the code:

include "wp-load.php";

$number = 5;

$the_query = new WP_Query(array(
  'showposts' => $number,
  'offset' => 1,  // This will cause the query to skip over first post
  'order' => 'ASC',
  'post__not_in' => get_option("sticky_posts"),
while ($the_query->have_posts()) : $the_query->the_post();

If you want to exclude all sticky posts from a query, use

query_posts(array("post__not_in" =>get_option("sticky_posts")));

(from the codex)

Looks like that will only work on 3.0 or greater, though: http://wordpress.org/support/topic/excluding-sticky-posts-using-query_posts

Edit: in response to your comment below, try this (I'm not sure this will work, but hopefully it will get you started):

$the_query = new WP_Query($args);

    while ($the_query->have_posts()) : $the_query->the_post();

        $do_not_duplicate = $post->ID; ?>
  • thanks for the response. since I'm not using query_posts() in my example, how would I integrate your answer in what I have to work with?
    – Scott B
    Aug 27, 2010 at 14:29
  • Scott, see above, I added some more. Aug 27, 2010 at 17:38

Travis' answer is fine if you're building your own query, for a secondary loop perhaps, but if you need to modify your main blog query, you can use pre_get_posts to filter out the sticky posts.

In the example below, I'm only excluding the sticky posts if the query is the blog page, as I still want sticky posts to be returned on taxonomy and search pages etc (I'm displaying sticky posts as featured articles on the main news page).

add_action( 'pre_get_posts', 'custom_post_archive_changes' );
function custom_post_archive_changes( $query ) {
    if ( is_home() && $query->is_main_query() ) {

        // exclude sticky posts from main news page
        $stickies = get_option("sticky_posts");
        $query->set( 'post__not_in', $stickies );


Just drop the snippet above in your functions.php file.

  • great, work even with ajax later
    – Iggy
    Jul 20, 2020 at 22:15

Just adding a more contemporary answer here, according to the Wordpress docs you can use ignore_sticky_posts as an argument to exclude sticky posts from a WP Query object. Here's an example altering the main loop on the posts page:

function wpstackexchange_exclude_sticky_posts( $query ) {
    if ( is_home() && $query->is_main_query() ) {
        $query->set( 'ignore_sticky_posts', true);
add_action( 'pre_get_posts', 'wpstackexchange_exclude_sticky_posts' );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.