Your task is to automatically complete URLs like the address bar in most browsers is doing. We will use the following (simplified) rules:

  • If the input string starts with http://, ftp:// or https://, return the string unchanged.
  • Otherwise, if the input string contains a dot ., e.g. in.put then the HTTP is assumed and http:// is prepended: http://in.put.
  • Otherwise ftp:// is prepended, e.g. ftp://input when the input string was input.


Any string which must not necessarily be a valid URL.


The string modified according to the above rules.

Test Cases

dan-pc -> ftp://dan-pc
https://localhost/ -> https://localhost/
ftp://foo -> ftp://foo
http://foo -> http://foo
f.oo -> http://f.oo
derp.me -> http://derp.me
another.one/ ->http://another.one/
// -> ftp://// 
a://b -> ftp://a://b

This is code golf, shortest code wins. Good Luck!

  • 2
    \$\begingroup\$ Can the input be abcd://site? (generally if there is something before :// can we assume it's http, https or ftp? \$\endgroup\$ – user202729 Apr 24 '18 at 0:14
  • \$\begingroup\$ nope. You do not have to take care of "invalid" input. Yes , your assumption is right @user202729 \$\endgroup\$ – 0x45 Apr 24 '18 at 0:18
  • 2
    \$\begingroup\$ Then which inputs are valid? \$\endgroup\$ – user202729 Apr 24 '18 at 0:18
  • 3
    \$\begingroup\$ I'd suggest adding a test case for http://foo \$\endgroup\$ – Chas Brown Apr 24 '18 at 0:42
  • 1
    \$\begingroup\$ Can the input be an arbitrary string? It looks like answers are assuming it's formatted like a URL. \$\endgroup\$ – xnor Apr 24 '18 at 2:31

12 Answers 12


R, 98 bytes


Try it online!

  • \$\begingroup\$ This won't quite work, for a couple of reasons: the regex . in the second grepl matches any single character, you need \\. instead. Additionally, the first grepl will match anything that has p:// or s:// as a substring; you need to use a regex like others have used, ^(https?|ftp):// \$\endgroup\$ – Giuseppe Apr 24 '18 at 16:58
  • \$\begingroup\$ Whoops, you're right about the latter grepl, fixed that. But the first one correctly matches all the test cases as they currently stand, I can update this if need be. Or is that considered bad form? \$\endgroup\$ – Punintended Apr 24 '18 at 17:04
  • \$\begingroup\$ The input is specified as Any string which must not necessarily be a valid URL. so I think you need that update. Which is annoying, to be sure. String challenges in R are seldom fun :( \$\endgroup\$ – Giuseppe Apr 24 '18 at 17:06
  • \$\begingroup\$ Damn, you're right. That'll learn me to read the instructions better. Fixed, and thanks for reigning me in =) \$\endgroup\$ – Punintended Apr 24 '18 at 17:12
  • \$\begingroup\$ not a problem, I've been burned so many times before...I must have ten or so answers I deleted for not meeting the specs that I never went back to. =P \$\endgroup\$ – Giuseppe Apr 24 '18 at 17:15

Perl 5 -p, 38 bytes


Try it online!


Ruby, 63 56 55 bytes


Try it online!

  • \$\begingroup\$ Erm your code just works if you supply the result in your code...? \$\endgroup\$ – 0x45 Apr 24 '18 at 11:05
  • 2
    \$\begingroup\$ They were hardcoded tests, now it should be more dynamic \$\endgroup\$ – lfvt Apr 24 '18 at 11:11

Swift, 147 133 bytes

Thanks to Herman L for saving 14 bytes.

Sadly, NSRegularExpression would've taken away lots of precious bytes.

import Foundation;let s=readLine()!,h=["http://","https://","ftp://"];print(h.contains{s.hasPrefix($0)} ?s:h[s.contains(".") ?0:2]+s)


import Foundation

let s = readLine()!, h = ["http://","https://","ftp://"]
print(h.contains{ s.hasPrefix($0) } ? s :h[s.contains(".") ? 0 : 2] + s)

Try it online!

  • 1
    \$\begingroup\$ I managed to remove a few bytes: TIO \$\endgroup\$ – Herman L May 3 '18 at 15:21
  • \$\begingroup\$ @HermanL Wow, impressive! Thank you. \$\endgroup\$ – Tamás Sengel May 3 '18 at 15:56

JavaScript (Firefox 52), 41 bytes

s=>new URL(s,/\./.test(s)?'http:':'ftp:')

If a string is required for output, add 3 bytes +'' at the end. (Notice this solution may add a trailing / at the end of domain name since they are the same URL)

s=>new URL(s,/\./.test(s)?'http:':'ftp:')

t=s=>console.log(`${s} -> ${f(s)}`)


It seems this only works on Firefox 52 ESR but not Firefox 60 or Chrome 65. So sad.


PHP, 59 bytes


To run all the tests:

cat <<EOF | php -nF <filename>

(Put a newline before the <?= for formatting, not required for one line of input)

Or just one at a time:

echo '<input>' | php -nF <filename>

Or Try it online!

  • \$\begingroup\$ I think you have to use a regex; your current code fails for the a://b example. \$\endgroup\$ – Titus Apr 24 '18 at 16:52
  • \$\begingroup\$ @Titus Oh, I didn't see that new test case. Thanks for letting me know. Do you think it'd be acceptable to just do 'p:' instead of ':', since it fulfills the test cases, or would it be more "right" to use a regex? \$\endgroup\$ – Ethan Apr 24 '18 at 17:09
  • \$\begingroup\$ I´d say it´d be fair to be precise, as all other submissions are so too: %^(ht|f)tps?://% should be ok though. \$\endgroup\$ – Titus Apr 24 '18 at 18:28

Java 8, 74 72 bytes


-2 bytes thanks to @HermanLauenstein.

Try it online.


s->                   // Method with String as both parameter and return-type
                      //  If the input starts with one of
                      //  "http://", "https://", or "ftp://"
   s                  //   Return it as is
  :                   //  Else:
   (s.contains(".")?  //   If it contains a dot
     "ht"             //    Start with "ht"
    :                 //   Else:
     "f")             //    Start with "f"
   +"tp://"+s         //   And append "tp://" and the input-String
  • 1
    \$\begingroup\$ -2 bytes using s->s.matches("(https?|ftp)://.*")?s:(s.contains(".")?"ht":"f")+"tp://"+s \$\endgroup\$ – Herman L Apr 24 '18 at 12:04
  • \$\begingroup\$ @HermanLauenstein Pretty obvious change now that I see it, but I hadn't thought of it at all, so thanks! :) \$\endgroup\$ – Kevin Cruijssen Apr 24 '18 at 12:09

Retina, 64 bytes


Try it online!


JavaScript, 64 bytes


JavaScript, 51 50 bytes, Real life assumption


Thank tsh for 1 byte

  • \$\begingroup\$ 'htt':'ft'}p -> 'ht':'f'}tp \$\endgroup\$ – tsh Apr 24 '18 at 2:24
  • \$\begingroup\$ Won't this fail for abcd://site? Expected output is ftp://abcd://site. \$\endgroup\$ – Shaggy Apr 24 '18 at 7:48
  • \$\begingroup\$ @Shaggy That's why I say "Real life assumption". In comment such are invalid input \$\endgroup\$ – l4m2 Apr 24 '18 at 8:49
  • \$\begingroup\$ No, the comments were clarifying that those inputs were valid but inputs with an invalid protocol should be treated the same as inputs with no protocol. The test cases have been updated to reflect this. \$\endgroup\$ – Shaggy Apr 24 '18 at 15:19

GolfScript, 58 55 bytes


Try it online!

This is my first GolfScript program, so I expect there is a lot room for golfing.


.'://':a/.,(\0=['https'.4<'ftp']:l?)*{}{.'.'?)!)l=a@}if Full program, implicit input
.                                                       Copy input
 '://':a                                                Push '://', and assign it to a
        /.                                              Split input at '://' and copy
          ,(                                            Push length of the result - 1 (<==> '://' in input)
            \0=                                         Pull up the array and get the first element
               ['https'.4<'ftp']:l                      Push [ 'https', 'http', 'ftp' ] and assign it to l
                                  ?)                    Test if first element is in that array
                                    *{}{            }if If at least one of those values is false
                                        .'.'?)          Push whether the input contains a dot
                                              !)        Logical not and increment:
                                                              '.' in input -> 1
                                                           no '.' in input -> 2
                                                l=      Get that element of l ([ 'https', 'http', 'ftp' ])
                                                  a@    Append a ('://') and input
                                                        Implicit output

Python 2, 87 85 bytes

lambda s:re.match('(https?|ftp)://',s)and s or['f','ht']['.'in s]+'tp://'+s
import re

Try it online!

-2 bytes thx to Titus and wastl

  • \$\begingroup\$ Maybe re.match(r'://',s) should be enough \$\endgroup\$ – tsh Apr 24 '18 at 2:23
  • \$\begingroup\$ @tsh: It´s not. Look at the latest test case. But I´d personally say that ^(ht|f)tps?:// should be ok. \$\endgroup\$ – Titus Apr 24 '18 at 18:28
  • \$\begingroup\$ I don't think ftps is considered a valid protocol. But you can save two bytes by removing r and ^ (re.match does only apply the regex at the beginning) \$\endgroup\$ – wastl Apr 25 '18 at 11:03

Pyth, 58 bytesSBCS


Test suite

Code contains unprintable characters, and as such does not display properly on Stack Exchange. The link provided contains these characters and is the correct version of the program.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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