Title: register_post_status
Published: April 25, 2014
Last modified: February 24, 2026

---

# register_post_status( string $post_status, array|string $args = array() ): object

## In this article

 * [Description](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#description)
 * [Parameters](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#parameters)
 * [Return](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#return)
 * [Source](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#source)
 * [Related](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#changelog)
 * [User Contributed Notes](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#user-contributed-notes)

[ Back to top](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#wp--skip-link--target)

Registers a post status. Do not use before init.

## 󠀁[Description](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#description)󠁿

A simple function for creating or modifying a post status based on the parameters
given. The function will accept an array (second optional parameter), along with
a string for the post status name.

Arguments prefixed with an _underscore shouldn’t be used by plugins and themes.

## 󠀁[Parameters](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#parameters)󠁿

 `$post_status`stringrequired

Name of the post status.

`$args`array|stringoptional

Array or string of post status arguments.

 * `label` bool|string
 * A descriptive name for the post status marked for translation. Defaults to value
   of $post_status.
 * `label_count` array|false
 * Nooped plural text from [_n_noop()](https://developer.wordpress.org/reference/functions/_n_noop/)
   to provide the singular and plural forms of the label for counts. Default false
   which means the `$label` argument will be used for both the singular and plural
   forms of this label.
 * `exclude_from_search` bool
 * Whether to exclude posts with this post status from search results. Default is
   value of $internal.
 * `_builtin` bool
 * Whether the status is built-in. Core-use only.
    Default false.
 * `public` bool
 * Whether posts of this status should be shown in the front end of the site. Default
   false.
 * `internal` bool
 * Whether the status is for internal use only.
    Default false.
 * `protected` bool
 * Whether posts with this status should be protected.
    Default false.
 * `private` bool
 * Whether posts with this status should be private.
    Default false.
 * `publicly_queryable` bool
 * Whether posts with this status should be publicly- queryable. Default is value
   of $public.
 * `show_in_admin_all_list` bool
 * Whether to include posts in the edit listing for their post type. Default is 
   the opposite value of $internal.
 * `show_in_admin_status_list` bool
 * Show in the list of statuses with post counts at the top of the edit listings,
   e.g. All (12) | Published (9) | My Custom Status (2) Default is the opposite 
   value of $internal.
 * `date_floating` bool
 * Whether the post has a floating creation date.
    Default to false.

Default:`array()`

## 󠀁[Return](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#return)󠁿

 object

## 󠀁[Source](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#source)󠁿

    ```php
    function register_post_status( $post_status, $args = array() ) {
    	global $wp_post_statuses;

    	if ( ! is_array( $wp_post_statuses ) ) {
    		$wp_post_statuses = array();
    	}

    	// Args prefixed with an underscore are reserved for internal use.
    	$defaults = array(
    		'label'                     => false,
    		'label_count'               => false,
    		'exclude_from_search'       => null,
    		'_builtin'                  => false,
    		'public'                    => null,
    		'internal'                  => null,
    		'protected'                 => null,
    		'private'                   => null,
    		'publicly_queryable'        => null,
    		'show_in_admin_status_list' => null,
    		'show_in_admin_all_list'    => null,
    		'date_floating'             => null,
    	);
    	$args     = wp_parse_args( $args, $defaults );
    	$args     = (object) $args;

    	$post_status = sanitize_key( $post_status );
    	$args->name  = $post_status;

    	// Set various defaults.
    	if ( null === $args->public && null === $args->internal && null === $args->protected && null === $args->private ) {
    		$args->internal = true;
    	}

    	if ( null === $args->public ) {
    		$args->public = false;
    	}

    	if ( null === $args->private ) {
    		$args->private = false;
    	}

    	if ( null === $args->protected ) {
    		$args->protected = false;
    	}

    	if ( null === $args->internal ) {
    		$args->internal = false;
    	}

    	if ( null === $args->publicly_queryable ) {
    		$args->publicly_queryable = $args->public;
    	}

    	if ( null === $args->exclude_from_search ) {
    		$args->exclude_from_search = $args->internal;
    	}

    	if ( null === $args->show_in_admin_all_list ) {
    		$args->show_in_admin_all_list = ! $args->internal;
    	}

    	if ( null === $args->show_in_admin_status_list ) {
    		$args->show_in_admin_status_list = ! $args->internal;
    	}

    	if ( null === $args->date_floating ) {
    		$args->date_floating = false;
    	}

    	if ( false === $args->label ) {
    		$args->label = $post_status;
    	}

    	if ( false === $args->label_count ) {
    		// phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralSingular,WordPress.WP.I18n.NonSingularStringLiteralPlural
    		$args->label_count = _n_noop( $args->label, $args->label );
    	}

    	$wp_post_statuses[ $post_status ] = $args;

    	return $args;
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-includes/post.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/6.9.4/src/wp-includes/post.php#L1418)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/6.9.4/src/wp-includes/post.php#L1418-L1499)

## 󠀁[Related](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#related)󠁿

| Uses | Description | 
| [_n_noop()](https://developer.wordpress.org/reference/functions/_n_noop/)`wp-includes/l10n.php` |

Registers plural strings in POT file, but does not translate them.

  | 
| [sanitize_key()](https://developer.wordpress.org/reference/functions/sanitize_key/)`wp-includes/formatting.php` |

Sanitizes a string key.

  | 
| [wp_parse_args()](https://developer.wordpress.org/reference/functions/wp_parse_args/)`wp-includes/functions.php` |

Merges user defined arguments into defaults array.

  |

[Show 1 more](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#)

| Used by | Description | 
| [create_initial_post_types()](https://developer.wordpress.org/reference/functions/create_initial_post_types/)`wp-includes/post.php` |

Creates the initial post types when ‘init’ action is fired.

  |

## 󠀁[Changelog](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#changelog)󠁿

| Version | Description | 
| [3.0.0](https://developer.wordpress.org/reference/since/3.0.0/) | Introduced. |

## 󠀁[User Contributed Notes](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#user-contributed-notes)󠁿

 1.   [Skip to note 5 content](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#comment-content-3927)
 2.    [ajfleming](https://profiles.wordpress.org/ajfleming/)  [  6 years ago  ](https://developer.wordpress.org/reference/functions/register_post_status/#comment-3927)
 3.  [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F%23comment-3927)
     Vote results for this note: 8[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F%23comment-3927)
 4.  `20` is the maximum character length for the `$post_status` parameter.
 5.  `wp shell
      wp> global $wpdb; wp> $wpdb->get_col_length('wp_posts','post_status')
     => phar:///usr/local/bin/wp/vendor/wp-cli/shell-command/src/WP_CLI/Shell/REPL.
     php:52: array(2) { 'type' => string(4) "char" 'length' => int(20) }
 6.  We’re able to register a post status with a `$post_status` parameter longer than
     20 characters, but we’re unable to save/update posts with it. Instead, the `wpdb-
     >process_fields()` method compares the converted data to the provided data and
     returns `false` because they’re different.
 7.   * It is still the case in February 27th of 2024. This should be better communicated
        to the users and the developers. Causes glitches and unexpected behavior.
      * [imddev](https://profiles.wordpress.org/imddev/) [2 years ago](https://developer.wordpress.org/reference/functions/register_post_status/#comment-6929)
 8.   [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F%3Freplytocom%3D3927%23feedback-editor-3927)
 9.   [Skip to note 6 content](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#comment-content-718)
 10.   [Codex](https://profiles.wordpress.org/codex/)  [  11 years ago  ](https://developer.wordpress.org/reference/functions/register_post_status/#comment-718)
 11. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F%23comment-718)
     Vote results for this note: 1[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F%23comment-718)
 12. **Example**
      An example of registering a post status called “Unread”:
 13.     ```php
         /**
          * Add 'Unread' post status.
          */
         function wpdocs_custom_post_status(){
         	register_post_status( 'unread', array(
         		'label'                     => _x( 'Unread', 'post' ),
         		'public'                    => true,
         		'exclude_from_search'       => false,
         		'show_in_admin_all_list'    => true,
         		'show_in_admin_status_list' => true,
         		'label_count'               => _n_noop( 'Unread <span class="count">(%s)</span>', 'Unread <span class="count">(%s)</span>' ),
         	) );
         }
         add_action( 'init', 'wpdocs_custom_post_status' );
         ```
     
 14.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F%3Freplytocom%3D718%23feedback-editor-718)
 15.  [Skip to note 7 content](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#comment-content-5517)
 16.   [Brent Leavitt](https://profiles.wordpress.org/brentleavitt/)  [  4 years ago  ](https://developer.wordpress.org/reference/functions/register_post_status/#comment-5517)
 17. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F%23comment-5517)
     Vote results for this note: 1[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F%23comment-5517)
 18. Something that was not clear in my understanding was the independent nature of
     Post Statuses in connection with Custom Post Types (CPT). I had always been under
     the assumption that a specific Post Status had to be linked to a specific post
     type, but the reality is that post statuses exist separate or independent from
     any post type or custom post type.
 19. From what I can see, the only place where Post Status is declared is within the
     code. A list of available post statuses can be generated from the global variable
 20.     ```php
         global  $wp_post_statuses;
         ```
     
 21. . These different post_status are not stored as list or array in the options table
     of database. The only place where post_status is used in the database is in the
     wp_posts table as the actual `post_status` value.
 22. To load a specific set of post_status values in the post editor screen (for example)
     is beyond the scope of this comment, but you will want to look into filtering 
     the values for the post_status as is relevant to your needs.
 23.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F%3Freplytocom%3D5517%23feedback-editor-5517)
 24.  [Skip to note 8 content](https://developer.wordpress.org/reference/functions/register_post_status/?output_format=md#comment-content-6931)
 25.   [Web Generation](https://profiles.wordpress.org/webgenerationnz/)  [  2 years ago  ](https://developer.wordpress.org/reference/functions/register_post_status/#comment-6931)
 26. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F%23comment-6931)
     Vote results for this note: 1[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F%23comment-6931)
 27. It seems that using the register_post_status function doesn’t add the new post
     status as an option in the edit post page, or quick edit either, which is disappointing.
     The issue, and some workarounds, is discussed in more detail here:
      [https://stackoverflow.com/q/20298346/612253](https://stackoverflow.com/q/20298346/612253)
     Hopefully it will help others avoid wasting as much time on the issue as I did!
 28.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F%3Freplytocom%3D6931%23feedback-editor-6931)

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fregister_post_status%2F)
before being able to contribute a note or feedback.