kellan 4:42pm, 13 April 2009
Super quick note, hopefully sufficient info.

The format for the short photo URLs is{short-photo-id}

A short photo id is a base58 conversion of the photo id. Base58 is like base62 [0-9a-zA-Z] with some characters removed to make it less confusing when printed. (namely 0, O, I, and l).

So that leaves an alphabet of: 123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ

I'm including below a variation of the code we use to do base conversion. Note it doesn't use modulus because PHP's modulus operator overflows for large numbers (like photo ids)

function base_encode($num, $alphabet) {
$base_count = strlen($alphabet);
$encoded = '';
while ($num >= $base_count) {
$div = $num/$base_count;
$mod = ($num-($base_count*intval($div)));
$encoded = $alphabet[$mod] . $encoded;
$num = intval($div);

if ($num) $encoded = $alphabet[$num] . $encoded;

return $encoded;

function base_decode($num, $alphabet) {
$decoded = 0;
$multi = 1;
while (strlen($num) > 0) {
$digit = $num[strlen($num)-1];
$decoded += $multi * strpos($alphabet, $digit);
$multi = $multi * strlen($alphabet);
$num = substr($num, 0, -1);

return $decoded;
blech​ PRO 7 years ago
Thank you. I was trying to reverse engineer the base58 string, and getting close, but no cigar. (If the photo ID space wasn't quite so sparsely populated where I was sampling it, I might have managed, too.)
alto maltés PRO 7 years ago
matt 7 years ago
Someone jam this in a twitter client, pronto!
Eli the Bearded 7 years ago
BC math is available in PHP.

bcmod -- Get modulus of an arbitrary precision number
Richard Cunningham PRO 7 years ago
It would be good if this was translatable to a photo url with out any requests (in the way twitpic, twitgoo, yfrog etc. do).

Just knowing the photo id doesn't get you to photo url since you need the secret, farm and server ( We would have to do a for each photo.

unless I'm missing something?
fraserspeirs 7 years ago
Here's an implementation of the encoding part in Objective-C:
Jiayong Ou 7 years ago
And here's an implementation in Ruby:
faygate PRO 7 years ago
Xenocryst @ Antares Scorpii Posted 7 years ago. Edited by dopiaza (admin) 5 years ago
An example for a bookmarklet:

javascript:void(prompt(' short ID (base58)',(function(num){if(typeof num!=='number')num=parseInt(num);var enc='', alpha='123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'; var div=num,mod;while(num>=58){div=num/58;mod=num-(58*Math.floor(div));enc=''+alpha.substr(mod,1) +enc;num=Math.floor(div);} return(div)?''+alpha.substr(div,1)+enc:enc;})(prompt('Flickr picture ID'))))

ETA: A more useful variant, giving you the respective, if activated on a photo display page, might be:

javascript:void((function(){var m=window.location.href.match(/^https?:\/\/[^/]*\bflickr\.com\/(photos\/[^/]+\/(\d+))/i);if(m.length&&m[2]) prompt('Short for\n"'+m[1]+'":',''+(function(num)
{if(typeof num!=='number')num=parseInt(num);var enc='';var alpha='123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';var div=num; while(num>=58){div=num/58;var mod=(num-(58*Math.floor(div)));enc=''+alpha.substr(mod,1)+enc;n um=Math.floor(div);}
stevefaeembra PRO Posted 7 years ago. Edited by stevefaeembra (member) 7 years ago
quick python snippet for encoding...

while num>=bc:
    enc = a[mod]+enc
    num = int(div)
enc = a[num]+enc
print "" % (enc,)
taiyofj PRO Posted 7 years ago. Edited by taiyofj (member) 7 years ago
javascript decoder.

function base58_decode( snipcode )
    var alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ' ;
    var num = snipcode.length ;
    var decoded = 0 ;
    var multi = 1 ;
    for ( var i = (num-1) ; i >= 0 ; i-- )
        decoded = decoded + multi * alphabet.indexOf( snipcode[i] ) ;
        multi = multi * alphabet.length ;
    return decoded;

I'm using above base 58 decode function on pbtweet
Wonderm00n PRO 7 years ago
Great topic kellan!

I've just used your base_encode function on

Tim Parenti PRO Posted 7 years ago. Edited by Tim Parenti (member) 7 years ago
Thanks for the information. I've created a simple, web-based implementation at

It's meant for the people who don't necessarily want or need Twitter integration, but just want to convert URLs (although I might add Twitter integration later).

It can handle conversions from a short URL to a photo ID and vice-versa. I'm planning to add full URL support so you can just paste a long URL from your browser bar and it will extract the relevant bit (the photo ID).

If anyone has any ideas to improve it, please let me know. Here's hoping someone at least finds it useful.
burntoutcar 7 years ago
Any reason why this can't be incorporated into the "Share This" widget at the top right of each photo page?
kellan 7 years ago
Btw valid paths after the photo id will be passed along now.

So$photoid/sizes/l works as do$photoid/nearby and$photoid/favorites
Kohichi PRO 7 years ago
python decoder snippet
This code based on taiyofj's javascript one,

def b58decode(s):
    alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
    num = len(s)
    decoded = 0 ;
    multi = 1;
    for i in reversed(range(0, num)):
        decoded = decoded + multi * ( alphabet.index( s[i] ) )
        multi = multi * len(alphabet)
    return decoded;
Rex Roof PRO 6 years ago
If these are really Base58, why doesn't the Math:Int2Base perl module work?
Rex Roof PRO 6 years ago
Oooh, because you aren't using regular Base58. you're using Base62 with your own characters removed. Sorry, answered my own question.
(robcee) PRO Posted 6 years ago. Edited by (robcee) (member) 6 years ago
my colleague Johnath converted this to a shorter Firefox bookmarklet using the page's contained <link rev="canonical"> tag:

cmort Posted 6 years ago. Edited by dopiaza (admin) 5 years ago
and a simple variation of @robceemoz's post to send it straight to twitter

javascript:var%20l=document.querySelectorAll("link"); for(i=l.length-1;i>=0;--i){if(/flic\.kr/.test(l.item(i).href)) document.location=''+l.item(i).href;}
bitrot Posted 6 years ago. Edited by bitrot (member) 6 years ago
I've just posted up a Greasemonkey script based on Xenocryst @ Antares Scorpii's bookmarklet (above):

It looks like this: short URL screenshot

Hope you find it useful!
kellan 6 years ago
Rex, don't know if you're still looking for a Perl module, but check out
andrhamm Posted 6 years ago. Edited by andrhamm (member) 6 years ago
Will there ever be the ability to use this URL shortening for sets?
opello PRO 6 years ago
I revised your initial check against m as such:


So that it doesn't introduce a javascript error when used on non-flickr pages (accidental clicks). I didn't see adding further error checking as worthwhile, but someone else might.
Zoolcar9 Posted 6 years ago. Edited by Zoolcar9 (member) 6 years ago
I wrote a Firefox extension to get shortened URL from context menu if you right click on Flickr photo, link, or Flickr photo page. Please try it

Please report any issues or suggestions at
or at Flickr Hacks group
frog23-net 6 years ago
Richard Barnett PRO 6 years ago
Any chance of redirecting to an page?
flowolf 6 years ago
i wrote a bash version to convert a photo ID into the base58 photo id and vice versa:

have fun
kellan 6 years ago
And I've added the much requested img urls.

Generalized form:$shortid_[stm].jpg

Fun fact: this was built for many years ago, I just added support for the short url identifiers.

Happy New Year
Jan Hapke 6 years ago
It would be cool if this also worked for sets. So we could use URLs like

Or generally more functions of flickr, like maybe slide shows, collections, you name it.

The problem is that set ids are very long (for some reason longer than photo ids) so the resulting short URLs might still be too long for twitter.
PetroleumJelliffe 6 years ago
Does the URL shortener only work for photos because you can still access photos with just their ID using this:

There isn't an equivalent for sets that I know of. That is, you need to know who created a set to access one, but for photos you don't.
Sybren A. Stüvel 6 years ago
Support for the short photo page URL has been included in version 1.4 of the Python FlickrAPI kit, released today. For more information see
jolinwarren 6 years ago
Here's an AppleScript version of the encoder in this post:

on base_encode(alphabet, num)
set base_count to count of alphabet
set encoded to ""
repeat while (num ≥ base_count)
set encoded to (item ((num mod base_count as integer) + 1) of alphabet) & encoded
set num to num div base_count
end repeat

if (num > 0) then set encoded to (item (num + 1) of alphabet) & encoded

return encoded
end base_encode
tjieftjaf 6 years ago
I use this function in MySQL:


DECLARE chars CHAR(58) DEFAULT "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
WHILE num > 0 DO
SET res = num % 58;
SET num = num DIV 58;
SET stream = CONCAT(MID( chars, res + 1, 1 ), stream);
RETURN stream;

END $$


And then in your SELECT, INSERT, etc.:

SELECT Title, CONCAT('', BASE58(Id)) FROM `Photo`;

Based on a post by Barry Gould on the MySQL forum.
whatsthatpicture PRO Posted 5 years ago. Edited by whatsthatpicture (member) 5 years ago
Hi, I'm not after Flickr's trade secrets, but is there any broad evidence as to how successful the implementation of short urls has been on Flickr, and how much they are used? I'm trying to get a feel for whether this is worth doing on a museums collection catalogue.
dopiaza PRO 5 years ago
I think it depends on how you expect your catalogue to get used. I see the short URLs bandied around a lot on Twitter, where space is at a premium, but I don't really see them much in other contexts.

When sharing URLs, I tend to prefer the long versions - you get more immediate contextual information that way.
scoopedup20 5 years ago
where is the callback url field
andre.laszlo 5 years ago
It should be noted that if you try kellan's php algorithm above and get your id from the rest api interface for example, you get utf-8 encoded data and the algorithm will not work unless you convert it to something that php can handle. Using iconv() for example. This is what happens when you end up with 4gLq58 all the time :)
alavoy 5 years ago
I posted an update to the Base 58 Objective-C Encoder to now include Decoding:
Milgrim 5 years ago
more python code:

alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
base = len(alphabet)

def b58encode(div, s=''):
    if div >= base:
        div, mod = divmod(div, base)
        return b58encode(div, alphabet[mod] + s)
    return alphabet[div] + s

def b58decode(s):
    return sum(alphabet.index(c) * pow(base, i) for i, c in enumerate(reversed(s)))
tjieftjaf 5 years ago
It looks like{short-set-id} is now working too!
daruyanagi 4 years ago
by C# (string class extention)

const string BASE58 = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";

public static long Base58Decode(this string input)
return BaseDecode(input, BASE58);

public static long BaseDecode(string input, string alphabet)
long decoded = 0, multi = 1;

foreach (var c in input.Reverse())
decoded += multi * alphabet.IndexOf(c);
multi *= alphabet.Length;

return decoded;

I made NuGet package to embed a photo on Flickr to your homepage. Please enjoy !


tarmo888 PRO 4 years ago
Would be nice if these 2 formats would be added to shorturl too.
richard.mark.ward 3 years ago
Sorry for dredging up a very old discussion - but how are the set ids encoded? using the base58 encoder / decoder for the short url / id seems not to match.
dmitriyk PRO Posted 3 years ago. Edited by dmitriyk (member) 3 years ago
Not that there's clamor for this, but here's a Scala Base58 encoder and decoder:

It's not letting me paste this inline for whatever reason, so grab the Gist.
dmitriyk PRO 2 years ago
In writing some unit tests for my application, I came across a curious and nonobvious property of Flickr's Base58 algorithm implementation that I feel should be documented somewhere.

For any given input to the encode() function, the range of the function does not include strings starting with the letter "1" Therefore, the domain of the decode() function similarly does not include strings starting with the letter "1" What actually happens is that decode(x) == decode("1" + x); that is to say, the space of unencoded IDs is not isomorphic to the space of encoded IDs.

If you pass a string starting with the letter "1" to decode, you're going to have a bad time. I've updated my own implementation of the algorithm to reflect that.
xGnarRx PRO 1 year ago
GO (golang) encoder:
func base58Encode(input int64) string {
alphabet := []rune("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ")
var a []rune
for input > 0 {
i := input % 58
input = input / 58
a = append(a, alphabet[i])
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
a[i], a[j] = a[j], a[i]
return string(a)
ifree0 7 months ago
Here is the emacs vesion of base-58-encode
(defun base-58-encode (num)
"Encode NUM to base58 encoded string."
(let* ((alphabet "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ")
(base-count (length alphabet))

(while (>= num base-count)
(setq div (/ num base-count))
(setq mod (- num (* base-count div)))
(setq result (concat (char-to-string (aref alphabet mod)) result))
(setq num div)
(when (> num 0)
(setq result (concat (char-to-string (aref alphabet num)) result)))
ifree0 7 months ago
Can I get better resolution than this$shortid_[stm].jpg? Or there is a way to get image's url from it't id?
Groups Beta