Remove Existing Self Linking Images in WordPress



Ahh, the self linking image, the bane of so many WordPress users. So, you have a site with a ton of content where unscrupulous publishers, admins, and contributors left the Attachment Display Settings “Link To” option to its dreaded default. Sure, you can prevent that moving forward and stop automatically hyperlinking images, but what about your existing content that’s riddled with self linking images (dare I call them “WP Selfies”)? I threw together a quick function—a dangerous function if used incorrectly—to remove self linking images from your existing content once and for all.


In case you missed that ^ please backup your database before using this snippet. That backup is the only way to undo this action. The action is even commented out in the snippet because you should only run this once and very deliberately (you’ll need to uncomment it when you’re ready). It could take a while depending on the amount of content you have. The site I used it on had ~500 posts and it took around 30 seconds.

This snippet parses each post’s or page’s content one by one. It looks for any img inside an anchor tag and if the image URL is the same as the anchor’s href URL then it replaces the entire anchor with just the img tag that was within it.

It’s not perfect but it got the job done for me. If you want to suggest improvements then please leave a comment.


  1. Thanks for this advice.


    Your PHP code changes were rolled back due to an error on line 27 of file wp-content/themes/x-child/functions.php. Please fix and try saving again.
    syntax error, unexpected '<'

    When removed it says same for P

    1. It’s possible that you copied the opening PHP tag (the “<?php”) which you shouldn’t need to do if you’re adding this to the bottom of your functions.php file. Seems like that would cause an error like this.

  2. Question: Can this be modified to remove ALL links from ALL images in every post? I imported a blog from blogger and am left with a ton of images that are still linked to the old site (so they are technically not ‘selfies’), every link also has a unique identifier for some reason so I can’t just swap out the url with a plugin just want to delete them all and leave them as ‘none’.

  3. This is a super useful snippet.

    It seems to work for me, however the load on my site stayed high even once it was complete. Even 24 hours later. The only way I could get load under control was to revert my wp_posts table from a backup. I even tried running the query a second time and the exact same thing happened.

    Any idea what could cause such strange behavior?

    I noticed that there were many “sleeping” MySQL processes that remained after running the snippet, up until I’d restore the table.

    Very strange!

    And a suggestion: how about using admin_init instead of init so that the snippet isn’t triggered to run over and over on sites that are highly trafficked?

    1. Thanks for the great suggestion, I immediately changed the hook to admin_init—really good idea.

      As for sleeping MySQL processes, it’s tough to say without actually seeing them. A workaround might be to run the script and then immediately upon completion export/dump the database which should be free of the self-linking images (WP Selfies), drop all tables as you would if you were restoring the original backup, and then instead of restoring the backup you can restore the export you made without the WP Selfies.

      Let me know if you have success with that and thanks again for the improvement!

  4. Followed all directions and received the following error:

    Fatal error: Call to undefined function get_current_site()

    Any idea what’s wrong?

    1. Seems that get_current_site() is just for WordPress multisite installations. Is there a way to run this without that method call?

    2. Sorry for the rapid-fire comments, but I ended up getting it to work. I found another (old?) version of the code here and was able to follow your directions above to get it to work.

      1. Thanks for the heads up about this Alex, it totally slipped under my radar. That old code doesn’t check the domain name of the WP selfies, which in some edge cases will remove WP selfies that may link to external sites. I now removed this function and was going to revise the check, but I still believe that even those edge cases are WP selfies and should be removed, so the old Gist code is now restored. If anyone has an issue related to edge cases like that then let me know and I can try to help if you’re stuck. Thanks again Alex!

  5. Be really careful with this script. It replaces ALL images that are linked. Not just the images that are linked to external WordPress pages on your own domain.

    1. You’re right, nice catch! I added an additional check (line 27) to ensure it only replaces images that are linked to the same domain.

  6. Great function. Thanks! 🙂
    But how exactly are you supposed to know when the function is finished?

    When I uncommented the action, my site was offline and the processes mysqld and php-fpm were almost at 100% hogging resources. The only way I could get my site online again (after 5 minutes for approx. 430 posts), was by commenting the action again. Is this the way it is supposed to work? How do you know when it is finished?

    1. This script only needs to run once. After that you can remove it. Depending on the number of posts you have, the script will run longer and may result in a “timeout”, meaning that your browser will stop waiting and show you a blank page. That doesn’t mean the script failed. The script will probably continue to run for a while (like in seconds) until it’s finished, but your browser decides not to wait any longer for a response (your browser is confused and doesn’t understand why it takes so long).

  7. Hello Michael,

    Many thanks for your solutions which saved us loads of time!

    For people who meet troubles to make it work, just few reminders:
    – DB backup
    – Copy the code to your functions.php file (Child theme)
    – When ready, uncomment the last line (//action… )
    – Save your file

    For us, it took about 1m30s for about 1800 posts. (WP 4.2.4)


    (and please don’t forget your DB backup)

  8. Hello, thanks for this post it’s very helpfull, but I haven’t been able to make it work. I copied this content on my function.php (Child theme) however nothing happends.
    Can someone help me with this problem, Thanks in advance.

  9. Thank you for publishing this. I just wrote a post on removing image links in WordPress. Your solution is solution Nr. 4, the only one working on existing posts with image links!

Leave a Comment