Get The First Image From a Post

Let's say you wanted to use the post thumbnail feature of WordPress, but had a whole archive of posts that would take too much time to go through. For new posts, you can be specific and use the feature as intended. For old posts, you just want to use the first image it finds in the content for the thumbnail, or a default if none present.

Add this to functions.php or make a functionality plugin:

function catch_that_image() {
  global $post, $posts;
  $first_img = '';
  $output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);
  $first_img = $matches[1][0];

  if(empty($first_img)) {
    $first_img = "/path/to/default.png";
  return $first_img;

To use it, use this code in the loop:

if ( get_the_post_thumbnail($post_id) != '' ) {

  echo '<a href="'; the_permalink(); echo '" class="thumbnail-wrapper">';
  echo '</a>';

} else {

 echo '<a href="'; the_permalink(); echo '" class="thumbnail-wrapper">';
 echo '<img src="';
 echo catch_that_image();
 echo '" alt="" />';
 echo '</a>';


I found that has_post_thumbnail wasn't as reliable as the logic above.

Reference URL


  1. Reece
    Permalink to comment#

    Thanks for this. Always on the lookout to add functionality to WP.


  2. TomTank4
    Permalink to comment#

    Great function, I am trying to add youtube functionality to this but am a bit stuck.

    I wanted it to grab the youtube thumbnail if it sees a youtube embed before it sees an image. Any ideas?

    • Robert Watcher
      Permalink to comment#

      I’m not familiar with how to make things work in WordPress – – – but I included similar functionality in my Journal which I recently rewrote (hand coded – not WordPress). It is based on my use of the iFrame Video Embed for HTML5 compatability in my Journal – so won’t work with object and embed code. Hopefully you can use it and adapt it to your WordPress application in a similar way as above with the first image.

      This video check code, comes after I have checked to see if there is an image in the content from a post (as I loop through). If it finds an iframe, it uses preg_match to extract the “src” of the iframe – and if there is a match to ‘’ – I can create a url based on the video id that is extracted from the src url.

      This is one of the pages that contains a couple of posts with Youtube video – where I got the Youtube images and display them –

      preg_match('|<iframe [^>]*(src="[^"]+")[^>]*|', $postcontent, $matches);
      $tmp_src = explode('/',$matches[1]);
      $vid_id = rtrim($tmp_src[count($tmp_src)-1], '"' );
      if($matches AND $tmp_src[2]==''){
      	$youtube_img_url = ''.$vid_id.'/hqdefault.jpg';
      	echo '<img src="'.$youtube_img_url.'" alt="You Tube Video" />';

      I have left out the extra if statements that check next for a Vimeo video url (which requries more complex code to extract) , as well as a default image if there is not a src url.

  3. Anon
    Permalink to comment#

    I have this in a page kind of like a small gallery but its limited due to:

    Settings >> Reading >> Blog pages show at most

    Is there a way around this to grab all images no matter what the limit is from settings?

  4. Goob
    Permalink to comment#

    I’ve been using the functions.php version of the code for a while now, but only recently discovered that this doesn’t seem to work for pages. Any chances there’s a way to make it apply to them as well?

  5. zhen yi

    Hi, i would like to ask what if i want to get the second image instead of the first one? Helps are much appreciated thanks

  6. Paul O'Flaherty

    That’s a great piece of code, thanks for sharing.

    I have a question though – if you were doing this from an attachment page (attachment.php) what would you change in the function to make it output correctly?



  7. Carlos Goncalves

    How Can I change the image size?

    • Aaron
      Permalink to comment#

      You should use some css:

      .thumbnail-wrapper img {width:300px;}

      If you want it to resize with the page use something like:

      .thumbnail-wrapper img {width:60%;}

  8. george
    Permalink to comment#

    Does anybody know how to get the first occurance of firstbigimage_big.jpg from:



  9. Suwandi Halim
    Permalink to comment#

    Thanks. Help my day.

  10. wow
    Permalink to comment#

    I found this high up in Google search, what a joke.

    Someone on should manage the snippets to not promote garbage code, preg matching the content for images tags..?..?

    WordPress already has a simple built in function for this called: get_children

    • Chris Coyier
      Permalink to comment#

      For anyone reading this troll’s post and is worried about it…

      get_children gets images that are associated with the post. Like you used the built in image uploader to upload the image. That’s not always the case, hence needing to parse for it (e.g. an embedded flickr photo).

    • Walter
      Permalink to comment#

      @chris no, get_children() gets thumbnails associated to a post. This code extracts from post content the first img html tag.

    • The Dro
      Permalink to comment#


  11. Steve
    Permalink to comment#

    Great tutorial. I would also like to know how to leverage this code to offer a dynamically sized image. It seems folks are using timthumb for this, I’m curious if there is a way to do it with core WP functions.

    It’s mentioned above that CSS can be used, but that’s not a great approach if you need to resize an image more than a few pixels. The goal is to deliver the image in a new size similar to how get_the_post_thumbnail($post->ID, array(80,80)); works. Thanks!

  12. Tori
    Permalink to comment#

    Thank you so much! I don’t know why after all this time, I just don’t check your page first when it comes to WordPress.

  13. nev
    Permalink to comment#

    I’d love to know how to use this logic in a child theme. I’ve hacked my child theme’s content.php so far to enable excerpts in the loop, but I’d really like the excerpt to show the first image in the post as well. Not got into making plugins yet, so I was hoping there might be a way, either by modifying my child theme’s content.php and/or its functions.php (crosses fingers) ;)

  14. nev
    Permalink to comment#

    OMG I did it! Thanks TONS for this code!!!

  15. nev
    Permalink to comment#

    This code is gold! It picks up the image if it’s a featured image or not. Brilliant! Thank you!!!

  16. Steph
    Permalink to comment#

    This is a great snippet, thanks for posting it.

    Just curious if anyone has successfully altered the function to return no IMG tag if no image is found instead of a placeholder? I’ve been tinkering with it but no joy, my PHP is rusty sadly.

    • Gareth
      Permalink to comment#

      Remove these two lines from the function:

      if(empty($first_img)) {
      $first_img = “/path/to/default.png”;

      and then…

      if ( $image = catch_that_image() )
      echo '’;

  17. flo
    Permalink to comment#

    great! what would be the code in order to show the LATEST image attached to a post. best, flo

  18. Barry
    Permalink to comment#

    For some reason this always gets the last image in a post and not the first. Used as is with a few posts with about 2 images in each.

    • Michelle
      Permalink to comment#

      To get the first image instead of the last, replace /i with /U in the regular expression

  19. nev
    Permalink to comment#

    @Barry – That’s strange – it’s taking the first image for me (i.e., the first image that appears in the post – the one nearest the top).

    I’m inserting the code inside a duplicated content.php in a child theme, directly after:


    div class=”entry-summary”>

    … in its own div.

    Seems to work for me.

  20. nev
    Permalink to comment#

    Just one problem – it returns the first image for listings in the loop, but not for category listings

  21. nev
    Permalink to comment#

    sorry – I meant, not for category listings where the first image is a featured image (I know I could get the first non-featured image, but I wondered if it could be tweaked to get the first featured image for category listings?

  22. nev
    Permalink to comment#

    Ah – I worked it out – just to add:

    || is_category()

    … to the conditional.


  23. Sai
    Permalink to comment#

    Is there anyway we can display an image for Only First Post?

  24. nev
    Permalink to comment#

    There’s a problem with the default image path when viewing category listings with pretty permalinks turned on – you get a broken image link because something like “images/default.jpg” is appended to the end of the permalink (e.g., “”).]

    Trying to think of a path to use that would cover all bases for that situation.

    • The Dro
      Permalink to comment#

      add a / before images. This way you’re doing a direct path from the root.

  25. Warrentier

    I tried the code; it did return the image …

    p.s. I wrote my posts using windows live writer 2012 and embed Facebook photo link in live writer)

    But I couldn’t get the returned image in thumbnail size… Also, the image appears on top of the posts on both the index and individual post.

    That makes two images (one thumbnail and a duplicate one inside the post)..
    . I’d like to get rid of the thumbnail when it’s in single post while only showing the thumbnail with float left on index page.

    What can I do?

    I am using my own child theme from twenty twelve …

    Many thanks in advance…

  26. Dan

    Thanks! Works like a charm :)

  27. Jordan Singleton

    This is how I handled it without regular expressions. I just put it in the template (in the loop of an archive page), but it wouldn’t be too hard to pull it into a function that could then be called in the template.

    <?php // Get thumbnail image
        if (has_post_thumbnail()) { 
        } else {
            $gallery_arguments = array(
            'post_type' => 'attachment',
            'post_mime_type' => 'image',
            'post_parent' => $post->ID,
            'numberposts' => 1);
            $gallery_images = get_children($gallery_arguments);
            if ($gallery_images) {
                foreach ($gallery_images as $post) {
                $image_attributes = wp_get_attachment_image_src($post->ID,'thumbnail');
                    <img src="<?php echo $image_attributes[0]; ?>">
            <?php } }
    • Mittens

      I actually got to this page because I was doing something similar to what you have.

      I really liked that way, however get_children will only work if said image is only used in the current post. Or at least that’s where it was used first.
      That’s because in the current WP version, post_parent has to be unique (an attachment can’t have multiple parents).

      Solutions to this can however be obtained by hacking around with plugins that duplicate attachment entries in the database for each new post (see here).

      Are you using any of those solutions?

  28. Archie Makuwa

    Hi guys,

    I am using a foundations theme and have followed the exact steps above. It works on the localhost (links to images in the right localhost path). The problem comes in on the live, the images path is that from the localhost:

    So basically it breaks. How to I turn the localhost url into a more dynamic one?

  29. Dan Gaz
    Permalink to comment#

    Perfectly Working! :) Many ThanX

  30. Salem
    Permalink to comment#

    I’m currently give up with the_post_thumbnail(); function at all and moving to use first_img instead from duplicate my work making thumbnail and inside post image ..

  31. Wendy
    Permalink to comment#

    I’ve been using this function for a while, now noticing that I’m getting a php notice in my error log, PHP Notice: Undefined offset: 0. for this line: $first_img = $matches [1] [0]; This post here: tells me I need to use isset() to check if something is in there first. Has anyone else experienced this? I’m only noticing this notice now, wondering what may have changed.

  32. DUKE
    Permalink to comment#

    i have a problem the default img not show & it show me the error:

    Notice: Undefined offset: 0 in /vagrant/wp-content/themes/advocacy/functions.php on line 51

    line 51: $first_img = $matches[1][0];

    can someone help me?

    • DUKE
      Permalink to comment#

      I found a solution that works for me:

      $output = preg_match_all(‘/<img.+src=\'”[\'”].*>/i’, $post->post_content, $matches);
      $first_img = $matches[1][0];


      if( $output = preg_match_all(‘/<img.+src=\'”[\'”].*>/i’, $post->post_content, $matches) )
      $first_img = $matches[1][0];

  33. AbhiM
    Permalink to comment#

    i am trying this.. but instead of getting image. i am getting only the link… can any one help me on this

  34. Jones
    Permalink to comment#

    This code looks very similar to an answer provided on StackOverflow.

  35. Carol Ann
    Permalink to comment#


    I’m not a programmer, but think I have stumbled upon your post looking for the right thing and was hoping you could help me integrate your code into the following code in my theme?

    Thanks in advance :)

    if ( has_post_thumbnail() )  ?>
        <div class="entry-image" style="<?php echo $max_height; ?>">
            if(!of_get_option('post_image_lightbox')){ ?>
                <a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>" rel="bookmark">
                    <?php the_post_thumbnail( $featured_image_size ); ?>
                $src = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), 'large', false, '' ); ?>
                <a href="<?php echo $src[0]; ?>" class="lightbox" title="<?php the_title(); ?>" rel="bookmark">
                    <?php the_post_thumbnail( $featured_image_size ); ?>
            } ?>
  36. Mike
    Permalink to comment#

    Is there a way to bypass the featured image and take the image that is listed first in the content? I’m using a child theme of twentythirteen and for some reason it will not crop my images when reducing it to thumbnail size. It just squeezes it into 100×100. So I’m forced to use a 100×100 image for my featured image (because I need a thumbnail displayed on my home page. I want to display the full size image on my page that displays my posts.

  37. eklotan
    Permalink to comment#

    thanks a lot. It works. great helpful.

  38. shahroz
    Permalink to comment#

    Hello sir please tell me how to use the second part of your code i mean how to add that code in a loop,sir i am a newbie so please help me thanks

  39. Nathan
    Permalink to comment#

    This is great! Great fallback when no thumbnail is set. Thanks!

  40. Nikolas

    Hi there.
    Thank you for your code. I’ve used it to display 4-5 random posts along with their first image.
    The code works fine but I would like to get the images dynamically resized. Using CSS is not an option since the images on my website are quite big and therefore loading 4-5 full size images below each post would make the site slow.

    So, is there a dynamic way to resize the image?

    Thank you in advance for your help :)

  41. Madhu

    Not working in custom post types .any one please provide a solution to this

  42. Vicento

    hey guys,
    I was wondering , what would it be needed to make it retrieve more than just the first one. maybe the first 4 images…. ?

    I think the array must be modified but i don’t understand it much…

  43. Kevin Hower

    First, thanks for this code! Second, I had the same undefined offset problem as some others had. So, what I did was leave the output line alone but change what came after that to :

    $first_img = $matches[1][0];
      if(empty($first_img)) {
        $first_img = "/path/to/default.png";
      return $first_img;

    in the function and then in my template i put this:

                &lt;a href=&quot;" &gt;
                  &lt;img src=&quot;" alt="" /&gt;

    I need to add some styling, but I’m still learning so I was more concerned with function for now than the style part. It also fixes the issue of having a default image show when there’s nothing to show, which was bugging me.

  44. Kevin Hower

    Well, crud, this just isn’t my day apparently. I thought I had pasted my own code but apparenty I pasted the original .

    THIS is actually what I did in the function:

    if (!empty($matches[1][0]) ) {
    $first_img = $matches[1][0];
    } else {
    $first_img = “”;
    return $first_img;

    Sorry for any confusion.

  45. Scott Fennell

    What’s the purpose of the $posts variable and output buffering? I tried it without either one and it worked fine. Here it is bundled up with an img tag and an alt attr:


    * Return an HTML img tag for the first image in a post content. Used to draw
    * the content for posts of the “image” format.
    * @return string An HTML img tag for the first image in a post content.
    function icicle_get_first_image() {

    // Expose information about the current post.
    global $post;
    // We'll trap to see if this stays empty later in the function.
    $src = '';
    // Grab all img src's in the post content
    $output = preg_match_all( '//i', $post-&gt;post_content, $matches );
    // Grab the first img src returned by our regex.
    if( ! isset ( $matches[1][0] ) ) { return false; }
    $src = $matches[1][0];
    // Sanitize for output
    $src = esc_url( $src );
    // Make sure there's still something worth outputting after sanitization.
    if( empty( $src ) ) { return false; }
    // Grab and sanitize the post title as an alt.
    $alt = esc_attr( $post-&gt;post_title );
    $out = "";
    return $out;


  46. Fabrício

    Hello, the code worked perfectly, however, I wonder how do I automatically generate a smaller image size, because it is loading the original image.

    I tried to do something like:

    add_image_size (‘thumb-medium’, 160, 140, true, array (‘center’, ‘top’));

    More unsuccessfully!

  47. Andy
    Permalink to comment#

    Hello, I want to show excerpt with first 300 characters of the post, how can I do it?

  48. komar
    Permalink to comment#

    Thanks for this. work for me.

  49. okita
    Permalink to comment#

    I tried this and it worked, but I have a problem with the fact that sometimes the first image turned out to be a smiley because it is also started with tag. Is there any way to exclude smilies from being selected as the first image?

    Tried to read about preg_match and regex but it’s way beyond my comprehension since I’m not a programmer myself.

  50. hesham
    Permalink to comment#

    Very helpful and works like a charm

  51. Helen
    Permalink to comment#

    Thanks so much for this tutorial and the one on Functionality plugin! I made my first plugin with the help of your tutorial and am so happy :)

    You and your site are the best!

  52. Naveen
    Permalink to comment#

    That is an awesome hack. One quick question, how to get the thumbnail of the non-featured image displayed using catch_that_image()?

  53. darknote
    Permalink to comment#

    How do I make all thumbnails are aligned to the left?
    Thank you

  54. Richard
    Permalink to comment#

    First, thanks for the tip on the function! But, like someone above, I got “Undefined offset”. After many hours of trial and error I stumbled on this code:

    function catch_that_image() {
    global $post, $posts;
    $first_img = '';
    if(preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches)){
    $first_img = $matches [1] [0];
    return $first_img;
    else {
    $first_img = get_template_directory_uri()."/images/default.jpg";
    return $first_img;

    This worked perfectly! Code from: Now, onto the next mission. Get this to only show the thumbnail of the caught image. God, I really need to learn php! ;)

    • Richard
      Permalink to comment#

      Almost a day later, after muuuch trial and errors and help from a lot of forum posts, I have come up with this:

      //Find first image in post
      function catch_that_image() {
      global $post, $posts, $wpdb;
      $first_img = '';
      if(preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches)){
      $first_img = $matches [1] [0];
      // Get the upload directory paths
      $upload_dir_paths = wp_upload_dir();
      // If this is the URL of an auto-generated thumbnail, get the URL of the original image
      $attachment_url = preg_replace( '/-\d+x\d+(?=\.(jpg|jpeg|png|gif)$)/i', '', $first_img );
      // Remove the upload path base directory from the attachment URL
      $attachment_url = str_replace( $upload_dir_paths['baseurl'] . '/', '', $attachment_url );
       // Run a custom database query to get the attachment ID from the modified attachment URL
      $attachment_id = $wpdb->get_var( $wpdb->prepare( "SELECT wposts.ID FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta WHERE wposts.ID = wpostmeta.post_id AND wpostmeta.meta_key = '_wp_attached_file' AND wpostmeta.meta_value = '%s' AND wposts.post_type = 'attachment'", $attachment_url ) );
      $thumb_url = wp_get_attachment_image_src($attachment_id,'thumbnail', true);
      //Get thumbnail metadata
      $metadata = wp_get_attachment_metadata($attachment_id);
      $height =  $metadata['sizes']['thumbnail']['height'];
      $width =  $metadata['sizes']['thumbnail']['width'];
      $alt_text = get_post_meta($attachment_id, '_wp_attachment_image_alt', true);
      $title_text = get_the_title($attachment_id);
      //$caption_text = get_post($attachment_id)->post_excerpt;
      // Build the <img> string
      $Thumb_image = '<a href="' . get_permalink() . '">' .
      '<img src="' . $thumb_url[0] . '" width= "'. $width .'" height="'. $height .'" alt="'. $alt_text .'" title="'. $title_text .'" />' .
      // Echo the thumb image
      return $Thumb_image;
      //If no image found, return a default image
      else {
      $first_img = get_template_directory_uri() . '/img/Default.png';
      return '<img src="' . $first_img . '" alt="Alt text" title="Title text" />';

      It will find the first image, then find the corresponding thumbnail and add width, height, alt and title to the output. You can also add the caption. Uncomment the row “//$caption_text” and add the caption in in the image string.
      To use it:

      <?php echo catch_that_image(); ?>

      Hopefully this will save some time for someone else!

  55. Surinder Kumar
    Permalink to comment#

    Thanks for this.

  56. Fred
    Permalink to comment#

    Thanks a lot, very usefull when working with content already in place that does not have featured images!

  57. Shreyasi
    Permalink to comment#

    Thank you so much. Great post. Helped me a lot.

  58. jberg1
    Permalink to comment#

    I was having problems with this code outputting the last image in the post, instead of the first. Not exactly sure why. But replacing the “preg_match_all” line with this, cured it.

    if(preg_match_all('/< *img[^>]*src *= *["\']?([^"\']*)/', $post->post_content, $matches)){

    Nice Code! Thanks.
    And thanks Richard for the version that delivers a sized thumbnail.

  59. Dreamer
    Permalink to comment#

    Does not work

    <link href="">
  60. Lee
    Permalink to comment#

    Thanks for the function.

  61. Imran Bughio
    Permalink to comment#

    How can this be used to render custom image size?

  62. sama web solutions
    Permalink to comment#

    Great functionality plugin :D

  63. Michael Thompson
    Permalink to comment#

    I would strongly suggest wrapping $post->post_content in do_shortcode() so that you also grab images from galleries or other shortcodes that put images in content.

    Doing that, the output line looks like this:

    $output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', do_shortcode($post->post_content), $matches);
  64. Alaeddine

    Awesome! Thanks

  65. WebDevz

    Exactly what I was looking for and it works great! Thank you!

Leave a Comment

Posting Code

We highly encourage you to post problematic HTML/CSS/JavaScript over on CodePen and include the link in your post. It's much easier to see, understand, and help with when you do that.

Markdown is supported, so you can write inline code like `<div>this</div>` or multiline blocks of code in in triple backtick fences like this:

  function example() {
    element.innerHTML = "<div>code</div>";

We have a pretty good* newsletter.