Get an attachment ID by URL in WordPress

We all know you can use wp_get_attachment_url() to return an attachment’s URL by passing in the ID, but what about the reverse scenario?

There are a lot of long-winded examples of how to get an attachment ID by URL floating around the interwebs. Most of them limit results to only returning images or use expensive DB queries. Really, there should be a function for this in core, but there isn’t.

Needless to say, I wasn’t really happy with any of the solutions I found people using, so I decided to take a stab at it.

Below is the most lightweight method I’ve come up with (so far) to get an attachment ID by passing through an attachment URL.

Example usage

Just as an example, this would echo the attachment ID integer of test-image.jpg onto the page:

<?php echo fjarrett_get_attachment_id_by_url( '' ) ?>

This would echo the same result as above because we are ignoring www usage in the URL being passed through:

<?php echo fjarrett_get_attachment_id_by_url( '' ) ?>

This would echo nothing, because the image doesn’t exist in the WordPress uploads directory:

<?php echo fjarrett_get_attachment_id_by_url( '' ) ?>

And finally, this would also echo nothing because the URL of the file is pointing to an external domain:

<?php echo fjarrett_get_attachment_id_by_url( '' ) ?>


We managed to fetch an attachment ID in just a few lines of code with no expensive DB queries! Awesome 😎

Now you can do cool things like turn a URL into an absolute path:

$url = '';
$attachment_id = fjarrett_get_attachment_id_by_url( $url );
$path = ( $attachment_id ) ? get_attached_file( $attachment_id ) : null;
echo $path;

For more information about what was used in this function, please see:

Was this code helpful to you? Let me know in the comments!


Add yours →

  1. What’s the use case for this function? I’m trying to think of why I’d need to look up a post associated with an uploaded file. Is it to obtain the attachment ID for an image that has been inserted into a post, one for which the ID-containing class name has been stripped?

    • Hey Weston, yeah that’s one possible use case for it.

      In one of my themes I have a post meta field where users can enter a URL to a file, either one from the Media Library or an arbitrary one hosted elsewhere.

      By using this function we can determine whether or not the file in question has an attachment ID, and if so, the path can be retrieved using get_attached_file( $attachment_id ) to then pass inside a PHP force download script using readfile() in order to create a “Download File” link.

      I plan to post that force download functionality in its entirety in my next tutorial.

      • I personally used a similar snippet found on stackexchange to get couple of different image sizes based on a single URL.

        I guess that adding wp cache to the db query could improve the snippet a bit.

  2. Is it safe to search the guid field? If someone changes the permalinks, or migrates urls without updating the guid field, this wouldn’t return anything even if the file actually existed.

    • Hey Jeremy! Thanks for your question.

      Changing permalinks on attachments in the WP Admin is not possible AFAIK. Even if you could, the GUID uses the actual file URL and not the permalink, which is a shortened URL using the attachment_id query string.

      Attachment media is the one exception to the “never touch GUID” rule. Since it uses the URL as the GUID it actually should be updated to the new hostname after a migration.

      However, the DB query in this function is using RLIKE to find a partial string match starting with the wp-content directory and ignores the hostname completely. E.g. wp-content/uploads/2013/05/test-image.jpg

      So even if you fail to update the GUID on attachments during a hostname migration, this function will still work (as long as the uploads directory hasn’t also changed).

  3. I needed a system to scrape posts for an image to use as a featured image, if a featured image was not provided. However, I didn’t want to show a large image as a post thumbnail, so I wanted to reverse the URL to attachment ID then retrieve the thumbnail version of the image.

    The one problem I faced was that your code does not work if the image is resized (eg, MyAmazingImage-250×150.jpg). Just add this code above the “global $wpdb;” line:

    $parse_url[1] = preg_replace( ‘/-[0-9]{1,4}x[0-9]{1,4}.(jpg|jpeg|png|gif|bmp)$/i’, ‘.$1’, $parse_url[1] );

  4. You are saying “…doesn’t exist in the WordPress uploads directory” but you are actually using the WP_CONTENT_URL directory to determine it, which is wrong.
    I keep the uploads directory outside the content directory as a rule for all my websites, and this would fail.

    You should use UPLOADS instead.

  5. Oh, never mind. I just noticed it’s just using it to determine hosts.
    Good work 😉

  6. Just wanted to say that I’ve tried several different variations of this that I’ve found online. This is by far the easiest to use and the smallest amount of code as well. Great snippet. Thanks.

  7. Thank you. It Works!

  8. such a shame, looking exact for this option, shows no error nor image 🙁

  9. The core function get_page_by_path() seems to almost do what you are trying to achieve. Unfortunately, it seems to be designed to return the parent of an attachment, if I read the code right. But the first 10 lines or so of that function should almost do it.


  10. It doesn’t work if the image source in content is not the original full size image, because then the src contains something like …-600×400.jpg and that can’t be found in wp_posts table, so another search should be done in wp_postmeta.

  11. WOW just what I was searching for. Came here by searching for dekalb county schools

  12. It seems not work with old wordpress multisites when the files are saved on “wp-content/blogs.dir” directory because I have urls like http://* What do you recommend?

  13. Is this script still available Frankie, would love to try it out.

  14. Frank, that’s a great solution.
    Can I use it in a commercial WP theme?

  15. Thanks for this awesome snippet. I was able to get the post thumbnail from a custom field url instead of the full size image which was in a custom folder inside the wp-content folder.

  16. I’m running into trouble using this code coupled with the fact that my media is physically stored in an AWS s3 bucket. However it still is linked in my database and can be attached to posts with all the normal wordpress functions.

    the way you have this set up it will return nothing because it see’s my media being stored elsewhere. Is there any way around that.

    I tried commenting out the line:

    if ( ! isset( $parsed_url[1] ) || empty( $parsed_url[1] ) || ( $this_host != $file_host ) ) {
    But it still returns nothing. Here is a sample of the url going into your function

    You can see it’s attachment url here :

    Any idea’s?

  17. Thanks for sharing. I will actually use this in a plugin that will be released soon on the wp-plugin directory. A link to this page is found in the sourcecode. 🙂

  18. Thanks you. I used for get a cropped version of the current image url.

  19. Thank you very much! This is the best solution I’ve found so far, especially for the domain-agnostic thing.

    I’ve featured this article here in stackoverflow:

  20. This code solves the problem of images like:
    and also use the UPLOADS folder 🙂

    function get_attachment_id_by_url($url) {
    global $wpdb;
    // Get the upload directory paths
    $upload_dir_paths = wp_upload_dir();

    // Split the $url into two parts with the wp-content directory as the separator
    $parsed_url = explode( parse_url( $upload_dir_paths['baseurl'], PHP_URL_PATH ), $url );
    // Get the host of the current site and the host of the $url, ignoring www
    $this_host = str_ireplace( 'www.', '', parse_url( home_url(), PHP_URL_HOST ) );
    $file_host = str_ireplace( 'www.', '', parse_url( $url, PHP_URL_HOST ) );
    // Return nothing if there aren't any $url parts or if the current host and $url host do not match
    if ( ! isset( $parsed_url[1] ) || empty( $parsed_url[1] ) || ( $this_host != $file_host ) ) {
    // Now we're going to quickly search the DB for any attachment GUID with a partial path match
    // Example: /uploads/2013/05/test-image.jpg
    $parsed_url[1] = preg_replace('/-[0-9]{1,4}x[0-9]{1,4}.(jpg|jpeg|png|gif|bmp)$/i', '.$1', $parsed_url[1]);
    $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}posts WHERE guid RLIKE %s;", $parsed_url[1] ) );
    // Returns null if no attachment is found
    return $attachment[0];

  21. Hi,

    thanks for the function, works great.

    I recommand to check if $attachment is empty before returning it, otherwise php will show a warning.

    if (!empty($attachment)) {
    return $attachment[0];

    return null;

  22. Hi,

    Some plugins use your code but this is not very optimised for big websites with a lot of images.

    A query is made on all posts of the table wp_posts, or he would already be easier to target only attachments. #better #faster #stronger 😀


Leave a Reply

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

%d bloggers like this: