New Facebook Photo Hacks

February 11th, 2009 at 10:14 UTC by Joseph Bonneau

Last March, Facebook caught some flak when some hacks circulated showing how to access private photos of any user. These were enabled by egregiously lazy design: viewing somebody’s private photos simply required determining their user ID (which shows up in search results) and then manually fetching a URL of the form:[uid]&id=[uid]
This hack was live for a few weeks in February, exposing some photos of Facebook CEO Mark Zuckerberg and (reportedly) Paris Hilton, before the media picked it up in March and Facebook upgraded the site.

Instead of using properly formatted PHP queries as capabilities to view photos, Faceook now verifies the requesting user against the ACL for each photo request. What could possibly go wrong? Well, as I discovered this week, the photos themselves are served from a separate content-delivery domain, leading to some problems which highlight the difficulty of building access control into an enormous, globally distributed website like Facebook.

Here’s an example “public link” of a photo of me in my office:

Posting this link shouldn’t be a privacy problem, as you shouldn’t be able to see a photo by following this link unless you’re in my network of friends. Facebook promotes this view by telling you at the bottom of the page that you can safely send this link out to friends, and in fact such links are posted all over the web if you search for them. Access rights are enforced on the Facebook page, so knowing this link doesn’t reveal the photo. But, unfortunately, the actual photo file is embedded in the page with the address:

Presumably, ‘’ stands for ‘Facebook Content Delivery Network,’ and the image is hosted here using a high-performance photo server which doesn’t have to do all the session management overhead of the larger site. Keep in mind that, as reported in October, Facebook is hosting 10+ billion photos, by some measures more than any other site on the web. If the URL of a photo were temporary and difficult to guess from the public address, this scheme might be okay. The photo server will in fact respond to a request from wget without any cookies at all. It has to, because it is in a different domain than the main Facebook site, and browsers are specifically designed to prevent transferring state between domains.

Unfortunately the link is neither temporary nor difficult to guess. The links appear to work indefinitely, based on trying some months-old ones floating around the web. Worse, most of the apparent randomness in the URL is not needed to access the photo. The following link is just as valid as the one posted above:

All we need is the actual filename of the photo, and I’ve reverse-engineered the filename format as:
Photo-size is just a character in the set {t, s, n} representing the resolution of the image, uid is the user ID of the user who uploaded the photo, pid is a photo ID, and PIN is a four-digit random number. I’m calling it a PIN because it was chosen to be four decimal digits, which can only be assumed to have been done in a foolish analogy to bank card security. It’s easy to learn everything but the PIN given a public link to the photo. Brute-forcing the PIN is also fairly easy: it’s a space of 9000, which can be searched in about 45 minutes using one script. This is also easily parallelisable, given that we can query any of the mirrored photo servers in the set {, …} we can get this down to under 2 minutes.

This is still a lot of work for one photo, but it gets better. Incrementing the photo ID by one reliably gives the next photo that was uploaded as part of the same album. Looking at the next few photos in sequence from the one posted above, the sequence of PINs is {4899,5210,5535,5857,6193,6524,6853}, giving deltas of {311,325,322,336,331,329}. These are almost certainly created by timestamping as the photos are received. So, given the public link to one photo, and doing one brute-force, we can pretty easily get the rest of the album with 10-20 queries per photo. I’ve coded this up and it works splendidly–the photo servers don’t appear to do any rate-limiting or blocking.

How to fix this problem? Obviously Facebook could check the session cookies for every photo request, but we’ll assume this is impractical given the current setup. If concede that using the knowledge of an opaque URL as a capability to view a photo is all we have to work with, then there is no reason not to increase the length of the PIN portion to be a cryptographically-strong 20 digits–it doesn’t need to ever be written or stored by a human. Of course, these must be generated randomly as photos are uploaded. It would also be prudent to have the PINs expire after an hour or so, as they aren’t meant to provide a permanent link, and may end up cached in all sorts of places. Finally, multiple requests with invalid PINs should lead to IP blocking to prevent crawling.

This is a smaller hole than the one from last year, as we need to find a public photo link first. As far as I can see, there’s no predictable pattern of photo IDs for given user IDs, so we can’t access photos for our arbitrary choice of user. Still, it is a privacy violation as Facebook promotes the view that public links won’t allow access to photos, when they actually do. Above all, it is an inexcusably sloppy design, especially given the bad press Facebook received for the original problems.

Entry filed under: Security engineering, Social networks

69 comments Add your own

  • 1. Alex  |  February 11th, 2009 at 11:26 UTC

    Note the giveaway “ak.” – fbcdn is indeed a CDN, but it’s actually Akamai Technologies’s CDN.

    1 ( 1.578 ms 1.871 ms 0.726 ms
    2 ( 26.429 ms 29.046 ms 29.954 ms
    3 ( 28.916 ms 26.863 ms 26.478 ms
    4 ( 26.052 ms 25.778 ms 24.490 ms
    5 ( 27.059 ms 28.777 ms 31.115 ms
    6 ( 30.019 ms 28.898 ms 26.221 ms

    Presumably they just offload all the images into the akamai instances and hope. To do better, they might need to move to something like Akamai Edge Computing, where they push app servers out to the edge – so they could serve images as if they were directly served from, but at the edge.

  • 2. Joseph Bonneau  |  February 11th, 2009 at 12:13 UTC

    Good observation–I suspected the use of a separate domain name for the photos is to enable the use of a third-party CDN. Curiously, some of my photos on the site are hosted within the domain, seemingly those which I uploaded from within the USA:

    Interestingly, it is much pickier about the URL, requiring the directory structure before the filename to be correct and making this attack more difficult (though it’s not clear this is meant as a security feature or is just an accident).

    Perhaps we are observing growing pains as Facebook uses Akamai and other third-party CDN’s to host it’s photos for Europe, where it doesn’t have it’s own server farms?

  • 3. Alex  |  February 11th, 2009 at 13:15 UTC

    LL = Limelight Networks, surely?

    1 ( 1.487 ms 0.727 ms 0.728 ms
    2 ( 25.536 ms 27.323 ms 27.866 ms
    3 ( 37.859 ms 34.327 ms 30.837 ms
    4 ( 23.448 ms 32.701 ms 25.258 ms
    5 ( 25.289 ms 37.723 ms 41.875 ms
    6 ( 97.004 ms 93.573 ms 93.150 ms
    7 ( 94.873 ms 125.412 ms 93.998 ms

    Interesting that they’re using multiple CDNs.

  • 4. Boyana  |  February 20th, 2009 at 00:06 UTC

    If that IS a picture of you then youre CUTE :)
    Thats all :)

  • 5. Juicy Theodore  |  February 22nd, 2009 at 20:58 UTC

    I agree with Boyana. More pix! ;-)

  • 6. M  |  February 22nd, 2009 at 21:34 UTC

    AFAIK you can use your own domains with Akamai. I know of at least one such website

  • 7. R  |  February 22nd, 2009 at 22:07 UTC

    Your second link “” is actually pointing to

    If you try to go to in your address bar it says “access denied”.

  • 8. Alex Polvi  |  February 23rd, 2009 at 00:32 UTC

    any idea who this is?


  • 9. jd  |  February 23rd, 2009 at 04:13 UTC

    SmugMug ran into an issue like this not long ago. It was actually pretty easy to access random pictures (you could do it by hand, didn’t even need a script), even for albums that were considered “private”. They ignored the problem until the bloggers discovered the loophole, finally generating enough attention (and negative publicity) so that SmugMug had to fix it.

  • 10. Chanux  |  February 23rd, 2009 at 05:19 UTC

    @Alex Polvi :D

    Actually gets the same weird photo :D

  • 11. Mark  |  February 23rd, 2009 at 18:24 UTC

    The simple fix of course is to replace the PIN with something useful, like a md5 or sha1 hash.

  • 12. Size?  |  February 23rd, 2009 at 20:01 UTC

    How is the photosize easily obtained from the original URL? I mean, certainly photos come in some standard sizes, but they don’t need to. One can crop something and upload the crop. So wouldn’t your brute force need to also guess the photo size for all PINs?

  • 13. php  |  February 23rd, 2009 at 20:15 UTC


    “This is a smaller hole than the one from last year”. There will always be a work around to a fix from facebook.

  • 14. Baggins  |  February 23rd, 2009 at 21:05 UTC

    @12: the photosize is the letter at the start of the filename, it is one of t, s, or n.

  • 15. I. C. London  |  February 23rd, 2009 at 22:00 UTC

    Thanks for the tip! Could be good to check out photos of the babes!

  • 16. v4lkyrius  |  February 23rd, 2009 at 22:14 UTC

    The script:


  • 17. v4lkyrius  |  February 23rd, 2009 at 22:38 UTC

    For the script, search Google Code for “fbcdngen”.

    (Sorry if this is a double-post.)

  • 18. 831  |  February 23rd, 2009 at 22:40 UTC

    They should learn from myspace photos. The file names consist of a letter denoting the size, and a hash of an unknown combination of variables, which probably include photoID, UID, albumID, timestamp, etc.

    The only way to get the URL to the photo is to visit the album, which is protected by privacy settings. And if the actual .jpg URL is shared, there is no personally identifiable or easily generated information in the filename

  • 19. Richard Wagnerius  |  March 3rd, 2009 at 05:25 UTC


    is there a way to use this with Windows?

  • 20. v4lkyrius  |  March 4th, 2009 at 17:58 UTC

    Richard Wagnerius,

    You could always use Cygwin.

    Porting to Python would also be trivial — I might do this in the next couple of days… (I was going to update the Google Code page with a more practical example soon anyway.)

  • 21. brunetton  |  March 11th, 2009 at 11:14 UTC

    Apparently things changed for PIN.

    Just uploaded a serie of photos today, the first is :

    and for the other :

    Photos have been uploaded at «the same time», I mean in the same group of photos using «upload all» in the java applet.

    I don’t see any timestamp here, it looks like 7 decimal random digits.

    I’ll really slow the process for brute force :(

    Hopefully, we always can check babe’s photos that have been uploaded before that filename change.

  • 22. v4lkyrius  |  March 11th, 2009 at 22:12 UTC


    In your example, the total number of digits is 22, as opposed to just 18 in the article. So, brute forcing your photos would theoretically take 10,000 times as much effort.

    However, in practice, “UID” is still constant, and “PID” are still sequential, so brute-force attacks (given a single known URL to begin with) remain entirely plausible.

  • 23. brunetton  |  March 12th, 2009 at 10:17 UTC

    v4lkyrius, indeed it remains possible, but it’ll be 1000x slower (minimum) :
    4 digits (with a small delta) –> 7 random digits

    It was just what I wanted to point

  • 24. Nancy  |  March 28th, 2009 at 15:24 UTC

    Sorry not a programmer but need to know if you do consider Facebook privacy secure. I am searching answers to advise if this is the right tech tool to use for teaching professionals who wish to communicate with other teaching professionals on a variety of topics (teacher unions advise against it).

  • 25. rocker  |  April 17th, 2009 at 10:05 UTC

    i’m trying your example v4lkyrius, my url_list now is 14GB and i’ve restricted the search from PID_MIN (00000000) to PID_MAX (01999999)… and it is still running!!

  • 26. AkiRoss  |  April 21st, 2009 at 11:38 UTC

    actually, you can’t use an hash as PIN, because hash is (should) be irreversible, while the server needs a quick way to associate a number to a filename. If hash were a feasible solution, it would be so easy to use just an MD5 for every file like [size][md5].jpg.

    I.e. given an md5 of the image, you can’t go back to the image/filename quickly. It would require a database to associate every hash to every file in one single enormous table.

    In addition, hashes aren’t so quick to generate. This is an high traffic server, i guess there are performance reason because they didn’t use an hash from the beginning.

  • 27. G  |  April 23rd, 2009 at 08:02 UTC

    is this still working??
    I see that the UID currently is more than 6 digits… so is this still working?

  • 28. G  |  April 23rd, 2009 at 09:50 UTC


    hello v4lkyrius
    is your code still working?
    I am not able to work on cygwin xargs
    it says command not found

    please help

  • 29. dude  |  April 26th, 2009 at 09:37 UTC

    man that 6 digits thing sucks
    cant find anything no more
    any ideas

  • 30. jack martin  |  May 30th, 2009 at 14:50 UTC

    so if I had some picture ids from a past friend whose albums are set to private how would I pull those up now?

    what would I put into those links to change it to the pic I want to see?

    thanks for help

  • 31. Tim  |  June 2nd, 2009 at 01:40 UTC

    The script still “works” with the longer UID and random 7-digit PIN, it’s just not practical anymore given the crazy size of the url_list.txt you are going to get. If it could be modified to create the URL, do the wget and get whatever is there to be gotten, and then move on to the next URL without creating that massive text file, that would be great. Could just leave it running forever.

  • 32. Jay  |  June 11th, 2009 at 02:55 UTC

    Poking around with this today. A few things: Facebook has moved to the larger numbers for new uploads, but this method is still practical for older files.

    However, when I try to use it, wget winds up eating up all my RAM and bringing my system to a grinding halt quickly. Is there a way to avoid this?

  • 33. jagga jatt  |  June 17th, 2009 at 13:41 UTC

    Is there a way to determine a PHOTO-ID for an unknown gallery given you have acess to one or more urls to different galleries?

  • 34. Voolex  |  August 7th, 2009 at 07:24 UTC

    Or simply, you can guess a friends password…. Most of them are using the ddmmyy format… Works every time…

  • 35. giraa2  |  September 4th, 2009 at 04:54 UTC

    There is a proven method available for accessing photos from private profiles, it is described in:

    It uses brute force attack approach! It works for me!!
    It was written in spanish but you can always use google translator or babylon…

  • 36. Anthony  |  September 6th, 2009 at 16:19 UTC

    I don’t care how long the PIN is; it’s still technically a security issue. If they’re using a 3rd party CDN with no intelligence aside from wget, that means that a “friend” can grab the true URL of a photo, post it somewhere, and that’s that.

    People are all caught up on the idea that a photo is secure, even on a CDN, as long as the URL is “unguessable”. But isn’t anyone concerned about an unguessable URL being acquired legitimately, but then posted somewhere it shouldn’t be, at which point there is no ACL to check permissions?

  • 37. Interweb Troll  |  September 8th, 2009 at 04:36 UTC

    Hey, could you figure out who uploaded the photo which has a filename ending in 13523613_3602037.jpg? I think it’s from an album, not a profile picture, hence it has a 5-string ID but I was only given two of the strings. I don’t know the user ID of the person (that’s what I’m trying to figure out). Any advice would be appreciated. Thanks.

  • 38. Sasha  |  November 9th, 2009 at 17:27 UTC

    Is there a way to figure out the sequence of the pin? For example, one of my pins (as you identify it) is .1273.

    If someone has that pin along with the [photo-size][uid]_[pid]_[pin], can they now view my other photos? Thanks!

  • 39. Rohan Tarun  |  December 4th, 2009 at 03:07 UTC

    I believe the script needs to be updated… as for there for the digits have been increased and extra numbers have been included…

    please kindly lend us the updated version

  • 40. Jat  |  December 27th, 2009 at 01:44 UTC

    This doesn’t work anymore does it? =[

  • 41. Bridget  |  December 30th, 2009 at 22:31 UTC

    For the fbcdngen script, how large is the text file supposed to be when you run with the old 4-digit pins? I had to stop mine because it was approaching 400 gigabytes (after I left the computer for a few hours) and was going to fill up my entire hard drive if I let it run much longer. I don’t know if it was looping infinitely or if those really are all individual values — if the latter, how does anyone have the hard drive space for the 7-digit pins..?

  • 42. Ugly51  |  January 24th, 2010 at 01:22 UTC

    Reference the post regarding the link:

    I was in the middle of experimenting with this URL, when my connection dropped out while the page was loading, leaving me with something quite interesting in my address bar. I had: a huge random sting]

    I think this may be of interest. Are Facebook hosting phots on

    The Zwunzi URL is not in my browser history, almost as though it never happened. Otherwise I would have posted the actual link here.

  • 43. anonymous17  |  January 29th, 2010 at 04:21 UTC

    too bad ugly51 that seems like a virus not any kind of photo hosting on the part of facebook.
    a quick google for zwunzi will tell.

  • 44. Arkhonx  |  March 3rd, 2010 at 19:57 UTC

    Is it possible to use this method to retrieve a recently deleted photo? The album’s open and stuff. I basically have everything but the pin and the server. They seem to be different from picture to picture although they’re in the same album.

    Thanks in advance!

  • 45. giorgos4  |  April 29th, 2010 at 23:10 UTC

    and what we can do when the name of the photo is something like this: it has a lot of digits..can i find the facebook source of this photo?

  • 46. T  |  May 3rd, 2010 at 20:59 UTC!/album.php?profile=1&id=1353807097

  • 47. Mike  |  May 17th, 2010 at 20:08 UTC

    Hey Joseph (and others),

    Take note of the direct link to images you’re ready to delete off of Facebook, delete them and check a few days later.

    If they’re still there, send them a message through the non-copyright infringement notice page with a list of those direct links.

    So far, I’ve been told it works.

    If enough people do it, then Facebook will have to address their privacy concerns before people quit and move to some of the newer sites opening up.

  • 48. 5th Street  |  June 14th, 2010 at 16:37 UTC

    It didn’t work! Help!!

    All I have is the user’s URL, I can’t even view the pictures… I tried copy pasting, that didn’t work either!

  • 49. 5th Street  |  June 14th, 2010 at 16:38 UTC

    It didn’t work! Help!!

    All I have is the user’s URL.. I can’t view the pictures.. I tried copy and paste, that didn’t work either!!

  • 50. 5th Street  |  June 14th, 2010 at 16:47 UTC

    It says “Content Not Found” WTH??!!

  • 51. Jhon Doe  |  July 28th, 2010 at 04:35 UTC

    Viewing private albums is actually easy if you stop trying to get your target friendship and focus on his/her friends. Why don’t we view our target profile logged as a friend he/she already has accepted? This idea is full explained in
    (in spanish, but you can use google translator)

  • 52. sally george  |  August 3rd, 2010 at 15:17 UTC

    hi ,
    please i want to know how can i search by photo in facebook?? or in tagged or my space or any site like that???
    i want to know if there is some one use my photos in a fake profile
    please i need your help

  • 53. anna  |  August 4th, 2010 at 10:26 UTC

    I use at work

  • 54. sudhir  |  December 13th, 2010 at 12:34 UTC

    Hi, I tried but your trick could not be understood by me.. Is there any possibility of allowing me to view this user’s private photo album???

    thanks in advance

  • 55. Arnoucheka  |  December 25th, 2010 at 16:45 UTC


  • 56. Arnoucheka  |  December 25th, 2010 at 16:49 UTC

    is there any possibility of allowing me to view this user s private photo album???

  • 57. Arnoucheka  |  December 25th, 2010 at 16:52 UTC

    is there any possibility of allowing me to view this user s private photo album

  • 58. Charizze  |  January 24th, 2011 at 02:38 UTC

    i clicked the link by accident and downloaded some file , is that bad ?

  • 59. haze  |  February 8th, 2011 at 05:18 UTC

    im confuse! can someone teach me, how to get the photo Id and the pin which has the 7 digit numbers. thank you

  • 60. Web Developer  |  February 12th, 2011 at 09:54 UTC

    Unless you know who you are looking for it is useless.

  • 61. berga  |  July 11th, 2011 at 12:58 UTC


    It seems that fbcdn filenames format has changed, and now looks like that :

    ID3 seems to be uploader’s ID, SIZE is in the same set as before.

    Did anyone worked on reversing this new format ?

  • 62. mancini02  |  August 5th, 2011 at 13:12 UTC

    I’m not much of a computer programmer but can you apply this technique to give me access to

    sophia’s photos?

  • 63. Gare  |  September 24th, 2011 at 17:19 UTC


    I think my fiancee is hiding something from me. In other words, sleeping with another guy. Her profile weblink is:
    her id=1032585243
    Massiel Galan

    I need help from someone that can help me view this profile. I know she is hiding something from me… I just need to verify.
    Please help! I am lost…


  • 64. farid  |  October 7th, 2011 at 04:11 UTC

    i need to see ’s photos

    help plz?

  • 65. meriaduz  |  January 6th, 2012 at 02:06 UTC

    With the actual links on fbcdn, the photos have now more IDs.

    PID = photo id;
    UID = user who uploads the photo;
    SIZE = the size in the picture, could be q, n, o and merely t, s…
    …but what about the others ID?!?!
    It looks like they want to make harder the way of getting those IDs, but we can get access to the pictures if knowing the URL.

  • 66. Vlad Kerper  |  July 3rd, 2012 at 21:32 UTC

    Me thinks this might be of some interest to you:

  • 67. Buy Streetwear  |  January 11th, 2013 at 15:33 UTC

    Good post however , I was wanting to know if you
    could write a litte more on this subject? I’d be very grateful if you could elaborate a little bit more. Appreciate it!

  • 68. Random  |  February 26th, 2013 at 12:22 UTC

    if someone knows how to do it and can do it for me, plz email me :D

  • 69. Get More Information  |  May 1st, 2013 at 20:56 UTC

    I am not sure where you are getting your information,
    but good topic. I needs to spend some time learning more or understanding more.

    Thanks for magnificent information I was looking for this info for my mission.

Leave a Comment


Required, hidden

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Subscribe to the comments via RSS Feed


February 2009
« Jan   Mar »