get_terms()WP 2.3.0

Retrieve the terms (items) of a given taxonomy or list of taxonomies by the given parameters.

Prior to 4.5.0, the first parameter of get_terms() was a taxonomy or list of taxonomies:

$terms = get_terms( 'post_tag', [
	'hide_empty' => false,
] );

Since 4.5.0, taxonomies should be passed via the 'taxonomy' argument in the $args array:

$terms = get_terms( [
	'taxonomy' => 'post_tag',
	'hide_empty' => false,
] );

From WP 4.6. meta-queries class was added - WP_Term_Query{}. And get_terms() function become a wrapper for this class.

You can use filters to modify the query in any way: before sending a query or you can control the output.

1 time — 0.015166 sec (extremely slow) | 50000 times — 33.29 sec (very slow) | PHP 7.1.11, WP 4.9.5
Hooks from the function



  • Array of WP_Term objects — on success.
  • array() (empty array) — when no terms were found.
  • WP_Error — when any of the specified taxonomies does not exist.
  • Number of found terms (as a string) — when fields = count.

Usage Template

$args = [
	'taxonomy'      => [ 'post_tag', 'my_tax' ], // tax name WP 4.5
	'orderby'       => 'id',
	'order'         => 'ASC',
	'hide_empty'    => true,
	'object_ids'    => null,
	'include'       => array(),
	'exclude'       => array(),
	'exclude_tree'  => array(),
	'number'        => '',
	'fields'        => 'all',
	'count'         => false,
	'slug'          => '',
	'parent'         => '',
	'hierarchical'  => true,
	'child_of'      => 0,
	'get'           => '', // set `all` to get all terms
	'name__like'    => '',
	'pad_counts'    => false,
	'offset'        => '',
	'search'        => '',
	'cache_domain'  => 'core',
	'name'          => '',    // to get terms by name field.
	'childless'     => false, // true - pass the terms which has child terms.
	'update_term_meta_cache' => true,
	'meta_query'    => '',

$terms = get_terms( $args );

foreach( $terms as $term ){
	print_r( $term );


get_terms( $args, $deprecated );
Array or string of arguments. See WP_Term_Query::__construct() for information on accepted arguments.
Default: empty array
Argument array, when using the legacy function parameter format. If present, this parameter will be interpreted as $args, and the first function parameter will be parsed as a taxonomy or array of taxonomies.
Default: ''

Arguments of $args

For a complete list of parameters, see the WP_Term_Query::__construct() method.

taxonomy(string/array) (required)
The name of the taxonomy to work with. You can specify multiple names as an array. Since WP 4.5, the taxonomies names passes to the first parameter of the function.
The maximum number of items that will be received. Limit.
Default: all.

Specify here a number or an array of numbers to get the terms whose object_id field of the wp_term_relationships table matches the specified values.

Usually, the object_id field contains the ID of the posts to which the term is attached.

An array of terms IDs to be included in the selection. When this parameter is specified, many others become useless. The value is passed through wp_parse_id_list().
Default: ''
An array of terms IDs that need to be excluded. You can also specify a comma-separated string of ids. The value is passed through
Default: ''
An array of parent terms IDs tree of which need to be excluded. The entire branch will be excluded. The value is passed through wp_parse_id_list().
Default: ''
Top indent in the SQL request — how many first rows to skip. You need to specify a number.
Default: 0

The field by which to sort the result. Can be:

  • id or term_id - by ID.
  • name - by name. By default.
  • count - by the term_taxonomy table count field - by the number of posts.
  • slug - by an alternative name.
  • description - by description.
  • term_group - by thr group.
  • parent - by the parent field.
  • include - by the order specified in the $include parameter.
  • slug__in - by the order specified in the $slug parameter. Since WP 4.9.
  • meta_value - by the value of the custom field.
  • meta_value_num - by the value of the custom field (the value will be interpreted as a number rather than a string).
  • key of "meta_query" - in the $meta_query parameter we specify parameters for custom fields query. Also we can specify array key for every set of such parameters. After that this key can be used as a key for sorting according to the corresponding metafield (custom field).
  • none - do not sort

For arbitrary sorting, you can use the YIKES Inc. Simple Taxonomy Ordering plugin.

Default: 'id'


The sort direction for the $orderby parameter:

  • ASC - from less to more (1, 2, 3; a, b, c).
  • DESC - in reverse order, from more to less (3, 2, 1; c, b, a).

Default: "ASC"

Whether to hide terms that have no entries. 1 (true) - hide empty, 0 (false) - show empty.
Default: true

What fields to return in the resulting array. Can be:

  • all - Return an array of objects (all data) - default.
  • ids - return an array of numbers.
  • names - return an array of strings.
  • count - returns the count of found terms.
  • id=>parent - return an array, where key = term_id and value = parent term ID.
  • id=>slug - return an array, where key = term_id and value = term slug.
  • id=>name - return an array, where key = term_id and value = term name.

Default: 'all'

true - returns the number of terms. In this case, the fields parameter is ignored.
false - returns an array of term objects.
Specify a string or an array of strings here, to get the terms with the specified slugs.
Default: ''

Whether to include terms that have non-empty child terms (that have posts). It means, that empty terms will be included in the array if their child terms have posts, even if the argument hide_empty = true.

  • true - yes, include.
  • false - no, dont include.

Default: true

Search by term name and term slug. Gets the terms name or slug of which contains specified string. I.e. the query looks like this: LIKE '%search_string%'.
Default: ''
Specify a string or array of strings here, to get the terms with the specified names.
Default: ''
Gets terms that have the specified string in their name. Search by name.
Default: ''
description__like (string)
Show terms that have a specified string in their description. Search by description.
Default: ''

If true, then the number that shows posts count of the parent categories becomes the sum of parent category posts and posts from it's child categories. By default, only self posts are counted.

It depends on the parent parameter because the counting works in PHP and if, for example, you specify parent=0, only the top terms will be obtained and pad_counts will not be able to correctly count the number of posts in the child terms. To work around this limitation, you need to get all the terms by not specify parent parameter at all, and then remove unnecessary terms in PHP... Here is an example of such code:

$terms = get_terms( [
	'hide_empty'  => 0,
	'orderby'     => 'name',
	'order'       => 'ASC',
	'taxonomy'    => 'category',
	'pad_counts'  => 1
] );

// leave only terms with parent=0
$terms = wp_list_filter( $terms, [ 'parent'=>0 ] );

Default: false


If specify all, following parameters will be force disabled: childless, child_of, hide_empty, hierarchical, pad_counts. "force" - means interrupt the current settings for these parameters. "Disabled" - means they will be set to false or 0.

Usually used for convenience, when you need to get terms, not for output, but for further work with them, this parameter allows you to not double check mentioned parameters...

// code snippet
if ( 'all' === $args['get'] ) {
	$args['childless']    = false;
	$args['child_of']     = 0;
	$args['hide_empty']   = 0;
	$args['hierarchical'] = false;
	$args['pad_counts']   = false;

Default: ''


ID of the parent term. Get the terms of taxonomy that are child of the specified term. The whole tree will be obtained (all nesting levels).

If multiple taxonomies are specified, the parameter is ignored.
Default: 0


true will skip (not get) terms that have child terms.

Has no effect on non-hierarchical taxonomies.
По умолчанию: false


The parent ID of the term to obtain only direct children.

Only the first nesting level will be obtained, not the whole tree as do parameter child_of. If you specify 0, the top-level terms will be displayed.
Default: ''

Enter a number or an array of numbers here to get the terms that have the field term_taxonomy_id matched the specified values.
Default: ''
Allows you to set an unique cache key to be used by get_terms() with WP object cache. For example, if to change the query you use one of the get_terms() filter (e.g. terms_clausses), setting this parameter, allow you to overwrite stored cache for identical queries.
Default: 'core'
true — load the metadata cache so you can retrieve it quickly. The cache is loaded for the received items.
Default: true
Query to retrieve terms by specified metadata. The parameter has many nested parameters, see WP_Meta_Query.
Get the terms with specified meta key. Can be used in conjunction with meta_value.
Default: ''
Get the terms with specified meta value. Always used in conjunction with meta_key.
Default: ''
MySQL operator used for comparing the meta value. See WP_Meta_Query::__construct() for accepted values and default value.
MySQL operator used for comparing the meta key. See WP_Meta_Query::__construct() for accepted values and default value.
MySQL data type that the meta_value column will be CAST to for comparisons. See WP_Meta_Query::__construct() for accepted values and default value.
MySQL data type that the meta_key column will be CAST to for comparisons. See WP_Meta_Query::__construct() for accepted values and default value.
Whether to suppress work of get_terms() filters (hooks)? If set to true, the filters will not work for the current request.
Default: false (filters enabled)
cache_results(true/false) (WP 6.4)

Whether to cache the results in the Object Cache.

This caching for terms has always been in place. In WP 6.2, it was moved to a separate cache group term-queries, and in 6.4, this parameter was added to allow disabling of the caching.

Default: true



#1 Get an array of all categories

The array data will be sorted by posts count in each category (orderby=count). Categories that have no posts will still be added to the array (hide_empty=0).

$myterms = get_terms( 'taxonomy=category&orderby=count&hide_empty=0' );

#2 Let's display a list of names of all terms of the taxonomy "my_taxonomy"

$terms = get_terms( 'my_taxonomy' );

if( $terms && ! is_wp_error( $terms ) ){
	echo '<ul>';

	foreach( $terms as $term ){
		echo '<li>'. esc_html( $term->name ) .'</li>';

	echo '</ul>';

In this example, each $term from the cycle foreach( $terms as $term ), will contain such information:

[term_id]     => 162
[name]        => Health
[slug]        => health
[term_group]  => 0
[term_taxonomy_id] => 170
[taxonomy]    => my_taxonomy
[description] =>
[parent]      => 0
[count]       => 2

#3 Show categories separated by a dot

An example of how to display categories joined with a separator · ( &middot; ):

// get all the terms from the my_term taxonomy
$terms = get_terms( [
	'taxonomy'   => 'my_term',
	'hide_empty' => false,
] );

// collect them and display
if( $terms && ! is_wp_error( $terms ) ){

	$items = [];

	foreach( $terms as $term ){

		$items[] = sprintf( 
			'<a href="%s" title="%s">' . esc_html( $term->name ) . '</a>', 
			esc_url( get_term_link( $term ) ),
			esc_attr( sprintf( __( 'View all post filed under %s', 'my_localization_domain' ), $term->name ) )


	echo sprintf( '<p class="my-term-archive">%s</p>', implode( ' · ', $items ) );

As a result, we get this code:

<p class="my_term-archive">
	<a href="URL" title="Name">Name</a> ·
	<a href="URL" title="Name">Name</a>

#4 Display current terms child terms as a list

Let's say we have a tree taxonomy with the following structure:

- Recipes
	- Cold dishes
	- Hot dishes
		- Porridge
			- In a slow cooker
			- In a saucepan
	- Cutlets

General task: show only the top level of child elements.


  • Being in the "Recipes" term, show "Hot dishes" and "Cold dishes".
  • Being in the "Cold dishes" term, do not show anything.
  • Being in the "Hot dishes" term, show "Porridge" and "Cutlets".
  • Being in the "Porridge" term, show "In a slow cooker" and "In a saucepan".
  • Being in the "In a slow cooker" term, do not show anything.


function first_child_terms_list() {

	$current_term = get_queried_object();

	// If the current page is not the page of the term, interrupt the execution
	if ( ! ( is_a( $current_term, 'WP_Term' ) ) ) {

	// If this is not a term of a tree taxonomy, interrupt the execution
	if ( ! is_taxonomy_hierarchical( $current_term->taxonomy ) ) {

	// Requesting the top-level child elements of the current term
	$terms = get_terms( [
		'taxonomy'   => $current_term->taxonomy,
		'parent'     => $current_term->term_id,
		'hide_empty' => false,
	] );

	// If there is a query error or there are no terms, interrupt the execution
	if ( is_wp_error( $terms ) || ! $terms ) {


	<ul class="terms">
	<?php foreach ( $terms as $term ): ?>

		<li class="term">
				'<a href="%s" class="term-link">%s</a>',
				esc_url( get_term_link( $term ) ),
				esc_html( $term->name )

	<?php endforeach; ?>


Call the function on a term page to display the HTML code:



Since 2.3.0 Introduced.
Since 4.2.0 Introduced 'name' and 'childless' parameters.
Since 4.4.0 Introduced the ability to pass 'term_id' as an alias of 'id' for the orderby parameter. Introduced the 'meta_query' and 'update_term_meta_cache' parameters. Converted to return a list of WP_Term objects.
Since 4.5.0 Changed the function signature so that the $args array can be provided as the first parameter. Introduced 'meta_key' and 'meta_value' parameters. Introduced the ability to order results by metadata.
Since 4.8.0 Introduced 'suppress_filter' parameter.

get_terms() code WP 6.5.3

function get_terms( $args = array(), $deprecated = '' ) {
	$term_query = new WP_Term_Query();

	$defaults = array(
		'suppress_filter' => false,

	 * Legacy argument format ($taxonomy, $args) takes precedence.
	 * We detect legacy argument format by checking if
	 * (a) a second non-empty parameter is passed, or
	 * (b) the first parameter shares no keys with the default array (ie, it's a list of taxonomies)
	$_args          = wp_parse_args( $args );
	$key_intersect  = array_intersect_key( $term_query->query_var_defaults, (array) $_args );
	$do_legacy_args = $deprecated || empty( $key_intersect );

	if ( $do_legacy_args ) {
		$taxonomies       = (array) $args;
		$args             = wp_parse_args( $deprecated, $defaults );
		$args['taxonomy'] = $taxonomies;
	} else {
		$args = wp_parse_args( $args, $defaults );
		if ( isset( $args['taxonomy'] ) && null !== $args['taxonomy'] ) {
			$args['taxonomy'] = (array) $args['taxonomy'];

	if ( ! empty( $args['taxonomy'] ) ) {
		foreach ( $args['taxonomy'] as $taxonomy ) {
			if ( ! taxonomy_exists( $taxonomy ) ) {
				return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );

	// Don't pass suppress_filter to WP_Term_Query.
	$suppress_filter = $args['suppress_filter'];
	unset( $args['suppress_filter'] );

	$terms = $term_query->query( $args );

	// Count queries are not filtered, for legacy reasons.
	if ( ! is_array( $terms ) ) {
		return $terms;

	if ( $suppress_filter ) {
		return $terms;

	 * Filters the found terms.
	 * @since 2.3.0
	 * @since 4.6.0 Added the `$term_query` parameter.
	 * @param array         $terms      Array of found terms.
	 * @param array|null    $taxonomies An array of taxonomies if known.
	 * @param array         $args       An array of get_terms() arguments.
	 * @param WP_Term_Query $term_query The WP_Term_Query object.
	return apply_filters( 'get_terms', $terms, $term_query->query_vars['taxonomy'], $term_query->query_vars, $term_query );