Given a valid goo.gl shortened link, output the original URL.


goo.gl/qIwi3N would give something like https://codegolf.stackexchange.com/. For input, you can choose to have the https?:// at the beginning, you can choose to have www. before the goo.gl, and you can also choose to get rid of the goo.gl if you only want the end of the URL. A slash at the end is optional for input and output. So, your input will end up matching the regex (https?://)?(www\.)?(goo\.gl/)?[A-Za-z0-9]+/?. For the output, you can choose whether or not to output https?://, whether or not to output www., and whether or not to output a trailing slash. However, you must be consistent with your I/O formatting.

I will say that you do not have to be consistent with https vs. http for output (but you must be consistent for input), as long as you are consistent with whether or not you include the whole https?:// part.

Test Cases

These are written with no https://, no www., no trailing slash in the input; yes https://, no www., and yes trailing slash in the output.

input -> output
goo.gl/HaE8Au -> https://codegolf.stackexchange.com/
goo.gl/IfZMwe -> https://stackoverflow.com/
goo.gl/JUdmxL -> https://chat.stackexchange.com/rooms/240/the-nineteenth-byte


  • You may assume that the shortened link will not point to another shortened link and that the destination site will return a status code of 2xx or 4xx (no redirections).

You can go here and enter a URL to apply the inverse operation of this: https://goo.gl/

  • \$\begingroup\$ @HelkaHomba fixed \$\endgroup\$
    – Pavel
    Commented May 13, 2017 at 4:47
  • 3
    \$\begingroup\$ Weather or notr to output a leading www. makes a difference. It is just in most cases the same server it refers to. Try for example http://pks.mpg.de and http://www.pks.mpg.de. The first cannot be resolved, while the latter can. \$\endgroup\$ Commented May 13, 2017 at 10:46
  • \$\begingroup\$ @StephenS Done, thanks for the suggestion. \$\endgroup\$
    – hyper-neutrino
    Commented May 13, 2017 at 12:21

6 Answers 6


CJam, 7 bytes


Test run

$ alias cjam
alias cjam='java -jar ~/.local/share/cjam-0.6.5.jar'
$ cjam unshorten.cjam <<< goo.gl/HaE8Au; echo
$ cjam unshorten.cjam <<< goo.gl/IfZMwe; echo
$ cjam unshorten.cjam <<< goo.gl/JUdmxL; echo

How it works

lg reads a line from STDIN and makes a GET request to that URL. The shortened URL issues a 301 redirect, which CJam doesn't follow. For the first test case, this pushes

<TITLE>Moved Permanently</TITLE>
<H1>Moved Permanently</H1>
The document has moved <A HREF="https://codegolf.stackexchange.com/">here</A>.

on the stack. Finally, '"/ splits at double quotes, and 5= gets the sixth chunk. Output is implicit.

  • 1
    \$\begingroup\$ I've tried 05AB1E and Pyth, they both follow the 301 :( \$\endgroup\$ Commented May 13, 2017 at 7:04

Bash, 28 24 bytes

curl -I $1|grep -oehtt.*

The output ends with a Windows-style newline, which I assume is acceptable.

Test run

$ bash unshorten.sh 2>&- goo.gl/HaE8Au
$ bash unshorten.sh 2>&- goo.gl/IfZMwe
$ bash unshorten.sh 2>&- goo.gl/JUdmxL

How it works

curl -I sends a HEAD request, so it fetches only the HTTP headers of the specified URL. For the first test case, it prints

HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Date: Sat, 13 May 2017 05:51:48 GMT
Location: https://codegolf.stackexchange.com/
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Transfer-Encoding: chunked
Accept-Ranges: none
Vary: Accept-Encoding

or similar. The output is piped to grep -oehtt.*, which displays only parts that match the specified regex, i.e., the string htt followed by any amount of characters up to the end of the line.

  • \$\begingroup\$ How does this work? \$\endgroup\$
    – Arjun
    Commented May 13, 2017 at 5:43
  • \$\begingroup\$ I've added an explanation. \$\endgroup\$
    – Dennis
    Commented May 13, 2017 at 5:53
  • \$\begingroup\$ Hehe, well explained! In that way i will learn bash soon :-D \$\endgroup\$
    – user69099
    Commented May 13, 2017 at 6:45
  • \$\begingroup\$ This performs wildcard expansion on htt.* so assumes no files matching it exist in the current directory. For most regexes, I'd agree on this site that the possibility of a file being matched are small enough that it's okay, but in this case, I don't think so, myself. The Linux kernel source code includes files named htt.c and htt.h, for instance. Changing it to grep -oehtt.* does not increase the byte count, but does make it significantly less likely to cause problems. \$\endgroup\$
    – hvd
    Commented May 13, 2017 at 8:30
  • \$\begingroup\$ @hvd I usually assume that the program is run in an otherwise empty directory, but -oehtt.* is a nice way to make it more reliable. \$\endgroup\$
    – Dennis
    Commented May 13, 2017 at 16:12

Python 2 + requests, 44 bytes

from requests import*
print get(input()).url

requests.get(URL) issues a GET request to the specified URL. The response object's url field contains the final URL, after any redirects. A protocol (e.g. http://) is required for the input, and the input is expected to be in quotes.

  • 1
    \$\begingroup\$ requests isn't built-in, so that needs to be added to the language header. \$\endgroup\$ Commented May 13, 2017 at 8:05
  • 1
    \$\begingroup\$ Use a lambda expression for -3 bytes \$\endgroup\$
    – ovs
    Commented May 13, 2017 at 11:56
  • 1
    \$\begingroup\$ @numbermaniac Whoops, you're right, I get so used to requests that I forget it's a third party lib. \$\endgroup\$
    – user45941
    Commented May 13, 2017 at 16:32

PHP, 36 Bytes

Input with https://



25 Bytes if Location: at the beginning must not removed


if Google changes the HTTP Header here is a safer version

preg_match("#Location: \K.*#",join("\n",get_headers($argn)),$t);echo$t[0];

Python 2, 43 bytes

Has no dependencies and is currently shorter than the other Python answer. shrug Input must match https?://goo\.gl/.*?/?

lambda s:urlopen(s).url
from urllib import*

NodeJS, 60 bytes


Input is in the format http://goo.gl/<id>.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.