Query posts by custom taxonomy term in WordPress

WordPress taxonomies are one of the most powerful content organization tools the platform provides. Categories and tags are the built-in examples, but developers regularly register custom taxonomies like genre, location, brand, or project-type alongside custom post types. At some point in almost every WordPress project you need to fetch all posts that belong to a specific term in one of those taxonomies. A theme might need to render a grid of portfolio items filtered by project type, a page template might loop through all products tagged with a particular brand, or a widget might list the three most recent articles in a chosen genre. The most reliable tool for this job is WP_Query with a tax_query parameter, which is designed exactly for taxonomy-based filtering. tax_query accepts an array of conditions that specify taxonomy name, term value, and the field type used for matching. You can match terms by ID, slug, or name — slug is usually the safest choice because term IDs change between development and production environments. WP_Query also respects post status, post type, and pagination arguments, so you can combine taxonomy filtering with other conditions in a single query instead of making multiple database calls. One critical detail to remember is that a custom WP_Query loop does not automatically restore the global $post object when it finishes. Forgetting to call wp_reset_postdata() after the loop breaks template tags like the_title() or get_the_ID() anywhere further down the same page. An alternative is get_posts(), which wraps WP_Query with simpler defaults and suppresses pagination filters, but gives you less control. For anything beyond a simple flat list, WP_Query with tax_query is the right approach. The example below fetches all published posts from a custom taxonomy called genre with the term slug thriller.

Problem: You need to retrieve all posts that belong to a specific term in a custom taxonomy.

Solution: Add the following code to your theme template file:

<?php
$args = array(
    'post_type'      => 'post',
    'post_status'    => 'publish',
    'posts_per_page' => -1,
    'tax_query'      => array(
        array(
            'taxonomy' => 'genre',
            'field'    => 'slug',
            'terms'    => 'thriller',
        ),
    ),
);

$query = new WP_Query( $args );

if ( $query->have_posts() ) {
    while ( $query->have_posts() ) {
        $query->the_post();
        the_title( '<h2>', '</h2>' );
    }
    wp_reset_postdata();
}

NOTE: Replace 'genre' with your custom taxonomy slug and 'thriller' with the target term slug. Setting 'posts_per_page' => -1 returns all matching posts at once — use a positive integer on large datasets to avoid memory issues. Always call wp_reset_postdata() after the loop to restore the global $post object and prevent template tag conflicts on the same page.