How can i get a list of all custom post types registered and show them on any template page.

I have code like this.


     * Template Name: Custom Post Types List


        'public'                => true,
        'exclude_from_search'   => false,
        '_builtin'              => false

    $output = 'names'; // names or objects, note names is the default
    $operator = 'and'; // 'and' or 'or'
    $post_types = get_post_types($args,$output,$operator);

    $posttypes_array = array();

    foreach ($post_types  as $post_type ) {
        $posttypes_array[] = $post_type;

    echo "<pre>";
    echo "</pre>";


  • 1
    Your code works fine. I just tested it. You do not have any custom post type registered which is public and exclude_from_search, that's why it's showing blank result. Try removing both of these args and see if page lists all default post types or not?
    – Robert hue
    Commented Nov 5, 2014 at 5:17
  • Try the codex example to make sure they are showing up at all codex.wordpress.org/Function_Reference/get_post_types#Examples
    – iyrin
    Commented Nov 5, 2014 at 5:56

5 Answers 5


Your code looks good. However, you can try the followoing codes to get all custom posts

    $args = array(
       'public'   => true,
       '_builtin' => false,

    $output = 'names'; // names or objects, note names is the default
    $operator = 'and'; // 'and' or 'or'

    $post_types = get_post_types( $args, $output, $operator ); 

    foreach ( $post_types  as $post_type ) {

       echo '<p>' . $post_type . '</p>';


you can also use a bunch of args to filter your result much. For details lists of args you can check the official WordPress Codex page: https://codex.wordpress.org/Function_Reference/get_post_types


If you want to get all post types as a list you need to use the get_post_types function and loop over the results with a foreach.

    // Get All Post Types as List
    foreach ( get_post_types( '', 'names' ) as $post_type ) {
        echo '<p>'.$post_type.'</p>';

These 2 lines of code can list all of your registered post types. If you want to know more about this get_post_types function visit the official wp codex page : https://codex.wordpress.org/Function_Reference/get_post_types

global $wp_post_types;

$posttypes = array_keys( $wp_post_types );

// Remove _builtins or others
$pt_remove = array("attachment","nav_menu_item","customize_changeset","revision");

foreach ( $posttypes as $posttype ):

 if ( in_array($posttype, $pt_remove) ) continue;

 $posttype_names[ $posttype ] = $posttype;


echo "<pre>";
echo "</pre>";
$args = array(
  'post_type'   => 'clients',
  'post_status' => 'publish',
  'tax_query'   => array(
        'taxonomy' => 'clients_service',
        'field'    => 'slug',
        'terms'    => 'therapy'

$testimonials = new WP_Query( $args );
if( $testimonials->have_posts() ) :
      while( $testimonials->have_posts() ) :
          <li><?php printf( '%1$s - %2$s', get_the_title(), get_the_content() );  ?></li>
else :
  esc_html_e( 'No clients in the therapy taxonomy!', 'text-domain' );

When the new WP_Query is called, the relevant clients are retrieved and we can loop through them. In the loop we simply output the title and the content of the client in a simple list.


Your code is correct. Your problem in the timing of executing both:

  1. Registering the CPT
  2. Calling the post type function you wrote.

You have one of 2 solution:

Solution 1:

Make sure your CPT is registered with higher priority before calling the get_post_types function.

Solution 2:

Reduce the get_post_types priority to start after CPT is registered.

add_action('init', 'your_function_name', 10);

I hope this help.

Thank you

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.