How to Get the Page or Post Title in WordPress (PHP)

To get the current page or post title in WordPress with PHP, use get_the_title(). It returns the title as a string and works with any post type, including pages, posts, and custom post types.

// Return the title
$title = get_the_title();

// Or echo it directly
echo get_the_title();

// Pass a post ID to get the title of a specific post
$title = get_the_title( 42 );

Below I’ll cover every common variation: getting a title by ID, the difference between the_title() and get_the_title(), escaping titles for HTML attributes, getting the site title, archive and blog-page titles, the document title in the browser tab, finding a post by its title, and the fastest way to fetch a raw title without WordPress filters.

If you landed here wanting the site name rather than a post title, that is get_bloginfo( 'name' ), covered in its own section below.

Key Takeaways
  • get_the_title() returns the current post’s title and accepts a post ID or a WP_Post object to fetch any other post’s title.
  • The site title (site name) is a different thing: get_bloginfo( 'name' ). The browser-tab title is a third thing: wp_get_document_title().
  • the_title() echoes; get_the_title() returns. Escape with esc_html() when you print a variable yourself.
  • On archives use get_the_archive_title(), and on the blog posts page use single_post_title(), because get_the_title() gives you the first post there.
  • Looking a post up by its title? get_page_by_title() was deprecated in WordPress 6.2; use WP_Query with the title argument.

Get the current post or page title

Inside the WordPress loop (or any template file where the global $post object is set), get_the_title() returns the current post’s title:

// Inside the loop
while ( have_posts() ) {
    the_post();
    $title = get_the_title();
    echo esc_html( $title );
}

It works in single.php, page.php, archive.php, and anywhere else inside a standard WordPress loop. Always esc_html() the output when rendering it as HTML content (WordPress escapes it for you in most core functions, but not when you echo a variable).


Get a title by post ID

Pass an integer post ID or a WP_Post object to get_the_title() to grab the title of any post, regardless of whether it’s the current one:

// Title of post ID 42
$title = get_the_title( 42 );

// Or pass a WP_Post object
$post_obj = get_post( 42 );
$title = get_the_title( $post_obj );

This is the method you want inside a custom WP_Query loop, a widget, a shortcode callback, or anywhere the global $post isn’t reliably set. You can get the post ID with get_the_ID() when you need it.

One thing to watch for: if the post is password-protected or private, WordPress automatically prepends Protected: or Private: to the title. Use get_post_field() (below) if you want the raw title without that prefix.


the_title() vs get_the_title()

WordPress has two similar-looking functions that do different things:

FunctionReturns or echoes?Typical use
get_the_title()Returns a stringWhen you need to manipulate the title (truncate, concatenate, pass to another function)
the_title()Echoes directlyWhen you want to print the title immediately, optionally wrapped in HTML

Quick side-by-side:

// the_title() with HTML wrapping (echoes immediately)
the_title( '<h1>', '</h1>' );

// get_the_title() when you need to process it first
$title = get_the_title();
$short_title = wp_trim_words( $title, 5 );
echo esc_html( $short_title );

When in doubt, reach for get_the_title(). It’s the more flexible option and you can always echo the result when you don’t need to manipulate it.


Use a title inside an HTML attribute

When a title goes inside an HTML attribute like title="" or alt="", use the_title_attribute(). It strips HTML tags and encodes quotation marks so your markup doesn’t break if the title happens to contain characters that would:

<a href="<?php the_permalink(); ?>"
   title="<?php the_title_attribute(); ?>">
    <?php the_title(); ?>
</a>

To return the escaped value instead of echoing it, pass echo=false:

$safe_title = the_title_attribute( array( 'echo' => false ) );

Get the WordPress site title

If you need the overall site name (not a post title), use get_bloginfo(). It returns whatever’s set in Settings → General:

// Site title
$site_title = get_bloginfo( 'name' );

// Site tagline / description
$tagline = get_bloginfo( 'description' );

// Home URL
$home_url = get_bloginfo( 'url' );

For a Multisite install, get_bloginfo( 'name' ) returns the current site’s title, while get_site_option( 'site_name' ) returns the network’s name.


Get the archive page title

On a category, tag, author, date, or custom taxonomy archive, get_the_title() will return the title of the first post in the loop, not the archive itself. Use get_the_archive_title():

// Returns something like "Category: Tutorials"
$archive_title = get_the_archive_title();

// Just the term name, no prefix
single_cat_title( '', false );     // category
single_tag_title( '', false );     // tag
single_term_title( '', false );    // any taxonomy
post_type_archive_title( '', false ); // CPT archive

To remove the Category: / Tag: prefix from get_the_archive_title() without switching functions, hook into the get_the_archive_title filter:

add_filter( 'get_the_archive_title', function( $title ) {
    return preg_replace( '/^[A-Za-z ]+:\s*/', '', $title );
} );

One archive-like page trips people up: the blog posts page you choose under Settings, then Reading. It is a page, but WordPress runs the main posts loop on it, so get_the_title() hands you the first post’s title rather than the page’s. single_post_title() reads the queried object instead, which on that page is the page itself:

// On the blog posts page the queried object is the page itself, not the first post
if ( is_home() && ! is_front_page() ) {
    $blog_title = single_post_title( '', false );
    // Equivalent: get_the_title( get_option( 'page_for_posts' ) )
}

Get a raw title without WordPress filters

get_the_title() runs the result through the protected_title_format, private_title_format and the_title filters, which is why password-protected posts come back with Protected: prepended and private ones with Private:. If you want the raw value straight from the database, use get_post_field():

$raw_title = get_post_field( 'post_title', 42 );

This is faster than get_the_title() when you’re fetching thousands of titles in a loop and don’t need filtering applied. Just remember to escape the output yourself (esc_html, esc_attr) since you’re bypassing the sanitization filters.


Get the document title (what the browser tab shows)

The title in the browser tab and in search results is a third thing again, assembled from the post title, the site name, pagination and the tagline. Since WordPress 4.4 any theme that declares add_theme_support( 'title-tag' ) (every block theme does) prints it through wp_get_document_title(), and you can read or reshape it with the same filters an SEO plugin uses:

// What WordPress will print inside <title> for the current request
$document_title = wp_get_document_title();

// Change the separator (the default is a hyphen)
add_filter( 'document_title_separator', function () {
    return '|';
} );

// Edit the parts before they are joined: 'title', 'page', 'tagline', 'site'
add_filter( 'document_title_parts', function ( $parts ) {
    $parts['site'] = 'SmartWP';
    return $parts;
} );

The parts array carries four keys: title, page, tagline and site, and pre_get_document_title lets you replace the whole string before any of that runs. If Yoast or Rank Math is active, it is already filtering here, so change the plugin’s settings rather than fighting it in code.


Find a post by its title

Sometimes the title is what you have and the post is what you want. The function everyone remembers, get_page_by_title(), was deprecated in WordPress 6.2 and its own docblock says to use WP_Query. The replacement is the title argument, added in 4.4, which does an exact match on post_title:

$query = new WP_Query( array(
    'post_type'      => 'page',
    'title'          => 'About Us',   // exact match on post_title
    'post_status'    => 'publish',
    'posts_per_page' => 1,
    'no_found_rows'  => true,
) );
$page = $query->have_posts() ? $query->posts[0] : null;

Exact means exact: case and punctuation have to match the stored title, and you will get whichever matching post the ordering returns first, so pass post_type and post_status to narrow it. If you find yourself doing this often, store the post ID somewhere instead; titles change, IDs do not.


Block themes: the Post Title and Site Title blocks

If your theme is a block theme, you are rarely writing any of this. The Post Title block outputs get_the_title() for whatever post the template is showing, the Site Title block outputs get_bloginfo( 'name' ), and the Archive Title block outputs get_the_archive_title(). The PHP above still matters inside plugins, shortcodes and custom blocks, but for templates the blocks are the same functions with a settings panel in front of them.


Frequently asked questions

How do I get the current post title in WordPress?

Call get_the_title() anywhere inside the WordPress loop or in a template file where the global $post is set. It returns the title as a string. Use the_title() if you want to echo it directly, optionally wrapped in HTML tags via the $before and $after arguments.

What is the difference between the_title() and get_the_title()?

the_title() echoes the title directly to the page and accepts optional $before and $after HTML wrappers. get_the_title() returns the title as a string so you can store, modify, or pass it to another function before output. Use get_the_title() when you need flexibility, the_title() when you just want it on the page.

How do I get a post title by ID in WordPress?

Pass the post ID to get_the_title(): $title = get_the_title( 42 );. It also accepts a WP_Post object. For the raw, unfiltered value (without the Protected: / Private: prefix WordPress adds), use get_post_field( 'post_title', $id ) instead.

How do I get the site title or site name in WordPress?

Use get_bloginfo( 'name' ). It returns the site title set under Settings → General. For the tagline use get_bloginfo( 'description' ), and for the home URL use get_bloginfo( 'url' ) or the more specific home_url() / site_url() functions.

Why isn’t get_the_title() working on my archive page?

On category, tag, author, and taxonomy archives, get_the_title() returns the title of the first post in the loop, not the archive name. Use get_the_archive_title() for the archive label itself, or reach for single_cat_title(), single_tag_title(), or post_type_archive_title() when you want just the term or post type name without the Category: / Tag: prefix.

How do I get the title without applying WordPress filters?

Use get_post_field( 'post_title', $id ). It reads the raw post_title column straight from the database, skipping the protected_title_format, private_title_format and the_title filters that get_the_title() applies. Faster in tight loops, and skips the Protected:/Private: prefix. Escape the output yourself with esc_html() or esc_attr() since you’re bypassing sanitization.

How do I get the title inside a custom WP_Query loop?

Call the_post() inside the loop to set up the global $post, then get_the_title() works as usual: while ( $query->have_posts() ) { $query->the_post(); echo esc_html( get_the_title() ); }. Don’t forget wp_reset_postdata() after the loop to restore the main query’s $post.

Does get_the_title() accept a post ID or a WP_Post object?

Yes, both. get_the_title( 42 ) returns the title of post 42, and get_the_title( $post_object ) works the same way. With no argument it uses the current post in the loop. It returns a string, never echoes, and applies the the_title, protected_title_format and private_title_format filters on the way out.

Is get_page_by_title() deprecated?

Yes, since WordPress 6.2. Its docblock points to WP_Query, whose title argument (available since 4.4) performs an exact match on post_title. Pair it with post_type, post_status and posts_per_page => 1 to get the single post you mean.

How do I get the title of the blog posts page?

Use single_post_title( '', false ), which reads the queried object (the page assigned under Settings, then Reading), or get_the_title( get_option( 'page_for_posts' ) ). Plain get_the_title() on that page returns the first post in the loop instead.

How do I get the title shown in the browser tab?

wp_get_document_title() returns the assembled document title for the current request, the same string WordPress prints in the <title> tag for themes with title-tag support. Adjust it with the document_title_parts and document_title_separator filters, or override it entirely with pre_get_document_title.


Bottom line

Most of the time you’ll want get_the_title(), with or without a post ID. Switch to the_title_attribute() when you’re dropping the title into an HTML attribute, get_bloginfo( 'name' ) when you need the site name, get_the_archive_title() on archive pages, single_post_title() on the blog posts page, and wp_get_document_title() for the browser tab. To go the other way and find a post from its title, use WP_Query with the title argument. For raw, unfiltered database values, get_post_field() is the escape hatch.

Related: how to get a post ID, get the current page slug, or browse the full WordPress code snippets library.

Picture of Andy Feliciotti

Andy Feliciotti

Andy has been a full time WordPress developer for over 15 years. Through his years of experience has built 100s of sites and learned plenty of tricks along the way. Found this article helpful? Buy Me A Coffee

8 Responses

  1. Great it works, thank you very much.
    Small question, how can I dynamically retrieve the title ID if I decide to delete it and recreate another one from my plugin?

    Here is his code:
    add_action(‘init’, function () {
    register_post_type(‘titlefooter’, [
    ‘label’ => ‘Footer titles’,
    ‘public’ => true,
    ‘menu_position’ => 3,
    ‘menu_icon’ => ‘dashicons-ellipsis’,
    ‘supports’ => [‘title’],
    ‘show_in_rest’ => true,
    ‘has_archive’ => true,
    ]);

    });

      1. No, sorry, that doesn’t work…
        I will search again on the web hoping to find a solution for my Wordpress theme.
        If not, I’ll think of another way to do it.
        Thank you again for your help.

Leave a Reply

Your email address will not be published. Required fields are marked *

WordPress Tips Monthly
Get the latest from SmartWP to your inbox.