Title: get_page_by_path
Published: April 25, 2014
Last modified: August 20, 2026

---

# get_page_by_path( string $page_path, string $output = OBJECT, string|array $post_type = 'page' ): 󠀁[WP_Post](https://developer.wordpress.org/reference/classes/wp_post/)󠁿|array|null

## In this article

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

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

Retrieves a page given its path.

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

 `$page_path`stringrequired

Page path.

`$output`stringoptional

The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
a [WP_Post](https://developer.wordpress.org/reference/classes/wp_post/) object, 
an associative array, or a numeric array, respectively.

Default:`OBJECT`

`$post_type`string|arrayoptional

Post type or array of post types. Default `'page'`.

Default:`'page'`

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

 [WP_Post](https://developer.wordpress.org/reference/classes/wp_post/)|array|null
[WP_Post](https://developer.wordpress.org/reference/classes/wp_post/) (or array)
on success, or null on failure.

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

    ```php
    function get_page_by_path( $page_path, $output = OBJECT, $post_type = 'page' ) {
    	global $wpdb;

    	$last_changed = wp_cache_get_last_changed( 'posts' );

    	$hash      = md5( $page_path . serialize( $post_type ) );
    	$cache_key = "get_page_by_path:$hash";
    	$cached    = wp_cache_get_salted( $cache_key, 'post-queries', $last_changed );
    	if ( false !== $cached ) {
    		// Special case: '0' is a bad `$page_path`.
    		if ( '0' === $cached || 0 === $cached ) {
    			return null;
    		} else {
    			return get_post( (int) $cached, $output );
    		}
    	}

    	$page_path     = rawurlencode( urldecode( $page_path ) );
    	$page_path     = str_replace( '%2F', '/', $page_path );
    	$page_path     = str_replace( '%20', ' ', $page_path );
    	$parts         = explode( '/', trim( $page_path, '/' ) );
    	$parts         = array_map( 'sanitize_title_for_query', $parts );
    	$escaped_parts = esc_sql( $parts );

    	$in_string = "'" . implode( "','", $escaped_parts ) . "'";

    	if ( is_array( $post_type ) ) {
    		$post_types = $post_type;
    	} else {
    		$post_types = array( $post_type, 'attachment' );
    	}

    	$post_types          = esc_sql( $post_types );
    	$post_type_in_string = "'" . implode( "','", $post_types ) . "'";
    	$sql                 = "
    		SELECT ID, post_name, post_parent, post_type
    		FROM $wpdb->posts
    		WHERE post_name IN ($in_string)
    		AND post_type IN ($post_type_in_string)
    	";

    	/** @var array<object{ ID: string, post_name: string, post_parent: string, post_type: string }> $pages */
    	$pages = $wpdb->get_results( $sql, OBJECT_K ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- The escaping has been applied above via esc_sql().

    	$revparts = array_reverse( $parts );

    	$found_id = 0;
    	foreach ( (array) $pages as $page ) {
    		if ( $page->post_name === $revparts[0] ) {
    			$count = 0;
    			$p     = $page;

    			/*
    			 * Loop through the given path parts from right to left,
    			 * ensuring each matches the post ancestry.
    			 */
    			while ( 0 !== (int) $p->post_parent && isset( $pages[ $p->post_parent ] ) ) {
    				++$count;
    				$parent = $pages[ $p->post_parent ];
    				if ( ! isset( $revparts[ $count ] ) || $parent->post_name !== $revparts[ $count ] ) {
    					break;
    				}
    				$p = $parent;
    			}

    			if ( 0 === (int) $p->post_parent
    				&& count( $revparts ) === $count + 1
    				&& $p->post_name === $revparts[ $count ]
    			) {
    				$found_id = $page->ID;
    				if ( $page->post_type === $post_type ) {
    					break;
    				}
    			}
    		}
    	}

    	// We cache misses as well as hits.
    	wp_cache_set_salted( $cache_key, $found_id, 'post-queries', $last_changed );

    	if ( $found_id ) {
    		return get_post( (int) $found_id, $output );
    	}

    	return null;
    }
    ```

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

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

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

Retrieves cached data if valid and unchanged.

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

Stores salted data in the cache.

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

Gets last changed date for the specified cache group.

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

Escapes data for use in a MySQL query.

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

Retrieves post data given a post ID or post object.

  | 
| [wpdb::get_results()](https://developer.wordpress.org/reference/classes/wpdb/get_results/)`wp-includes/class-wpdb.php` |

Retrieves an entire SQL result set from the database (i.e., many rows).

  |

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

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

Retrieves the URL to embed a specific post in an iframe.

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

Resolves numeric slugs that collide with date permalinks.

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

Maybe enable pretty permalinks on installation.

  | 
| [WP::parse_request()](https://developer.wordpress.org/reference/classes/wp/parse_request/)`wp-includes/class-wp.php` |

Parses the request to find the correct WordPress query.

  | 
| [WP_Query::is_page()](https://developer.wordpress.org/reference/classes/wp_query/is_page/)`wp-includes/class-wp-query.php` |

Determines whether the query is for an existing single page.

  | 
| [WP_Query::is_single()](https://developer.wordpress.org/reference/classes/wp_query/is_single/)`wp-includes/class-wp-query.php` |

Determines whether the query is for an existing single post.

  | 
| [WP_Query::get_posts()](https://developer.wordpress.org/reference/classes/wp_query/get_posts/)`wp-includes/class-wp-query.php` |

Retrieves an array of posts based on query variables.

  | 
| [WP_Query::parse_query()](https://developer.wordpress.org/reference/classes/wp_query/parse_query/)`wp-includes/class-wp-query.php` |

Parses a query string and sets query type booleans.

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

Examines a URL and try to determine the post ID it represents.

  |

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

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

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

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

 1.   [Skip to note 4 content](https://developer.wordpress.org/reference/functions/get_page_by_path/?output_format=md#comment-content-542)
 2.    [Codex](https://profiles.wordpress.org/codex/)  [  11 years ago  ](https://developer.wordpress.org/reference/functions/get_page_by_path/#comment-542)
 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%2Fget_page_by_path%2F%23comment-542)
     Vote results for this note: 6[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%2Fget_page_by_path%2F%23comment-542)
 4.  **Page Path**
      This is the equivalent of the `pagename` query, as in: `index.php?
     pagename=parent-page/sub-page`.
 5.  Code for the above could be written as (assuming `parent-page/sub-page` is actually
     the path to a page):
 6.      ```php
         get_page_by_path('parent-page/sub-page');
         ```
     
 7.  For non-hierarchical custom post types, you need to use just the slug in tandem
     with the `post_type` parameter.
 8.      ```php
         //Returns nothing, assumes animals is the rewrite slug for the animal CPT
         get_page_by_path('animals/cat', OBJECT, 'animal');
     
         //Returns the animal with the slug 'cat'
         get_page_by_path('cat', OBJECT, 'animal');
         ```
     
 9.  The functions `basename()` and `untrailingslashit()` are handy for grabbing the
     last part of the URL for this:
 10.     ```php
         $page_path = 'animals/cat/';
         get_page_by_path( basename( untrailingslashit( $page_path ) ) , OBJECT, 'animal');
         ```
     
 11.  * [`wp_basename()`](https://developer.wordpress.org/reference/functions/wp_basename/)
        is the i18n friendly version of `basename()`.
      * [Joy](https://profiles.wordpress.org/joyously/) [8 years ago](https://developer.wordpress.org/reference/functions/get_page_by_path/#comment-2811)
 12.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fget_page_by_path%2F%3Freplytocom%3D542%23feedback-editor-542)
 13.  [Skip to note 5 content](https://developer.wordpress.org/reference/functions/get_page_by_path/?output_format=md#comment-content-5773)
 14.   [Michael Bragg](https://profiles.wordpress.org/michaelbragg/)  [  4 years ago  ](https://developer.wordpress.org/reference/functions/get_page_by_path/#comment-5773)
 15. [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%2Fget_page_by_path%2F%23comment-5773)
     Vote results for this note: 2[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%2Fget_page_by_path%2F%23comment-5773)
 16. As per [scottb79](https://developer.wordpress.org/reference/functions/get_page_by_path/#comment-2967),
     it is correct that the function checks for the post type supplied (Page by default)
     and Attachment by default.
 17. This function will add the Attachment post type to any instances where the post
     type is passed as a string. Due to the following code:
 18.     ```php
         if ( is_array( $post_type ) ) {
           $post_types = $post_type;
         } else {
           $post_types = array( $post_type, 'attachment' );
         }
         ```
     
 19. If you truly only want to return the item path from only the post type supplied.
     
     It needs to be passed as an array like this:
 20.     ```php
         $page = get_page_by_path( 'example', OBJECT, [ 'page' ] );
         ```
     
 21. This issue was found when an attachment sotred in the database had the same path
     as the page we wanted to retrieve.
      The attachment having a lower Post ID it is
     returned first.
 22.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fget_page_by_path%2F%3Freplytocom%3D5773%23feedback-editor-5773)
 23.  [Skip to note 6 content](https://developer.wordpress.org/reference/functions/get_page_by_path/?output_format=md#comment-content-2967)
 24.   [scottb79](https://profiles.wordpress.org/scottb79/)  [  8 years ago  ](https://developer.wordpress.org/reference/functions/get_page_by_path/#comment-2967)
 25. [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%2Fget_page_by_path%2F%23comment-2967)
     Vote results for this note: -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%2Fget_page_by_path%2F%23comment-2967)
 26. If you don’t specify a `post_type,` it searches both `page` and `attachment`.
 27. If you want only `page`, pass it via the third parameter.:
 28.     ```php
         get_page_by_path( '/about/', OBJECT, 'page' );
         ```
     
 29.  * To achieve this, the third parameter would need to be passed as an array. `
        array( 'page' )`
      * [markcallen](https://profiles.wordpress.org/markcallen/) [8 years ago](https://developer.wordpress.org/reference/functions/get_page_by_path/#comment-3046)
      * The function parameters and defaults would suggest otherwise but you’re right.
        by default it will search in the attachments too. Though the code will still
        append the ‘attachment’ post type if you pass a string for the $post_type parameter.
        The only way to avoid it is to pass an array containing only ‘page’. ` get_page_by_path('/
        about/', OBJECT, array('page') ); ` It is also a quite slow query, especially
        if you have a lot of images in the site, hence it is really recommended to 
        do force only the ‘page’ post_type.
      * [piccart](https://profiles.wordpress.org/piccart/) [8 years ago](https://developer.wordpress.org/reference/functions/get_page_by_path/#comment-3087)
 30.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fget_page_by_path%2F%3Freplytocom%3D2967%23feedback-editor-2967)

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