diff --git a/autonym.py b/autonym.py
index 4d80523b3b8abedb6bfed2c7d541148fcc3fc092..f933c2462e4c00a926e545039e266c6958872d87 100755
--- a/autonym.py
+++ b/autonym.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import os
 import sys
@@ -35,16 +35,16 @@ class bcolors:
 def menu():
     """ Print menu and wait for user choice """
     os.system(['clear', 'cls'][os.name == 'nt'])
-    print bcolors.GREEN + "----- AUTONYM - for zax type nyms -----" + bcolors.ENDC
+    print(bcolors.GREEN + "----- AUTONYM - for zax type nyms -----" + bcolors.ENDC)
     if anym is False:
-        print bcolors.RED + "active nym: NONE"
+        print(bcolors.RED + "active nym: NONE")
     else:
-        print bcolors.GREEN + "active nym: %s " % anym.name
+        print(bcolors.GREEN + "active nym: %s " % anym.name)
     if re.match("OK", config['last_message']):
-        print bcolors.YELLOW + "\ndebug: %s\n" % config['last_message'] + bcolors.ENDC
+        print(bcolors.YELLOW + "\ndebug: %s\n" % config['last_message'] + bcolors.ENDC)
     else:
-        print bcolors.RED + "\ndebug: %s\n" % config['last_message'] + bcolors.ENDC
-    selection = raw_input("Enter\n\
+        print(bcolors.RED + "\ndebug: %s\n" % config['last_message'] + bcolors.ENDC)
+    selection = input("Enter\n\
     1 to choose/select active nym\n\
     2 to write a message (as active nym)\n\
     3 to create a nym\n\
@@ -72,11 +72,13 @@ def menu():
         updateNym(delete=True)
         menu()
     elif selection == "6":
-        print "\nsecret keys in your keyring:"
+        print("\nsecret keys in your keyring:")
         gpgfuncts.listSecKeys()
-        print "\n"
-        gpgfuncts.createKey()
-        print "key generated, secret keys in your keyring: "
+        print("\n")
+        email = input("Insert nym email address: ")
+        name = input("Insert name: ")
+        gpgfuncts.createKey(email, name)
+        print("key generated, secret keys in your keyring: ")
         gpgfuncts.listSecKeys()
         pressKey()
         menu()
@@ -89,7 +91,7 @@ def menu():
     elif selection == "q":
         sys.exit("bye bye")
     else:
-        print "wrong selection"
+        print("wrong selection")
         pressKey()
         menu()
 
@@ -112,7 +114,7 @@ def createNym():
         menu()
 
     if not gpgfuncts.selectKey(email):
-        print "no key available, creating a new one for %s" % email
+        print("no key available, creating a new one for %s" % email)
         gpgfuncts.createKey(email, name)
 
     subj_type = chooseSubjType(config)
@@ -131,7 +133,7 @@ def createNym():
 
 
 def updateNym(delete=False):
-    print "Choose nym to update/delete:"
+    print("Choose nym to update/delete:")
     askNym()
     dest = "config@" + anym.domain
 
@@ -140,7 +142,7 @@ def updateNym(delete=False):
         menu()
 
     if not gpgfuncts.selectKey(anym.name):
-        print "no key available for %s" % anym.name
+        print("no key available for %s" % anym.name)
         menu()
 
     if not anym['passphrase']:
@@ -155,7 +157,7 @@ def updateNym(delete=False):
             if isAscii(subject):
                 break
             else:
-                print "ERROR: subject contains not ascii characters, try again"
+                print("ERROR: subject contains not ascii characters, try again")
                 pressKey()
                 continue
 
@@ -199,9 +201,9 @@ def prepareSetupMsg(keyid, subj_type, subject):
     try:
         msg = "\n%s: %s\n\n" % (subj_type, subject) + key
         return msg
-    except UnicodeDecodeError, e:
-        print 'Unicode Error: ', e.reason
-        print 'Please use only plain ascii characters'
+    except UnicodeDecodeError as e:
+        print('Unicode Error: ', e.reason)
+        print('Please use only plain ascii characters')
         pressKey()
         menu()
 
@@ -231,7 +233,7 @@ def sendMixMsg(dest, msg, subj="subject", test=False, chain=""):
     args.append('--chain=' + ','.join(config['remailer_chain']))
 
     try:
-        mix = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        mix = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8")
         out, err = mix.communicate(msg)
         if err.find('Error') >= 0:
             raise MixError('Mixmaster process returned the following error: ' + str(err) + '. Sending failed.')
@@ -256,7 +258,7 @@ def writeMessage(subject="", recipient="", text="", test=0):
             if isAscii(subject):
                 break
             else:
-                print "ERROR: subject contains not ascii characters, try again"
+                print("ERROR: subject contains not ascii characters, try again")
                 pressKey()
                 continue
 
@@ -266,12 +268,12 @@ def writeMessage(subject="", recipient="", text="", test=0):
             if isAscii(subject):
                 break
             else:
-                print "ERROR: subject contains not ascii characters, try again"
+                print("ERROR: subject contains not ascii characters, try again")
                 pressKey()
                 continue
 
     if recipient == "":
-        recipient = raw_input("Insert recipient email address or newsgroup name: ")
+        recipient = input("Insert recipient email address or newsgroup name: ")
 
     if text == "":
         if X_is_running():
@@ -280,16 +282,16 @@ def writeMessage(subject="", recipient="", text="", test=0):
             text = editMessage()
         text = filter(lambda x: x in string.printable, text)
         if isGpg(text):
-            print "message already encrypted"
+            print("message already encrypted")
             pressKey()
         elif gpgfuncts.encrypt("test", recipient, test=True).status == "encryption ok":
             # really bad fix to solve a ridiculous problem, first line gets removed...  to be investigated
             text = "Message:\n" + text
             text = gpgfuncts.encrypt(text, recipient)
-            print "message has been encrypted with %s public key" % recipient
+            print("message has been encrypted with %s public key" % recipient)
             pressKey()
         else:
-            print "msg has not been encrypted, public key for %s not found" % recipient
+            print("msg has not been encrypted, public key for %s not found" % recipient)
             pressKey()
 
     msg = "From: %s\n" % anym.name
@@ -325,10 +327,10 @@ def chooseChain(chain=""):
     if chain != "":
         config['remailer_chain'] = [chain]
         return
-    print "\nChoose remailer chain used to send the message to the nymserver\n"
+    print("\nChoose remailer chain used to send the message to the nymserver\n")
     for remailer in uptime_sort_m():
-        print format_stats(remailer)
-    chain = raw_input('Choose remailer to be chained (by num), separated by commas, or write "r" for a random chain (3 remailers): ')
+        print(format_stats(remailer))
+    chain = input('Choose remailer to be chained (by num), separated by commas, or write "r" for a random chain (3 remailers): ')
     if chain == "r":
         config['remailer_chain'] = ['*','*','*']
         return
@@ -346,13 +348,13 @@ def validateChain(chain):
 
     if len(chain.split(',')) > 1:
         if not comma.search(chain):
-            print bcolors.RED + "ERROR - remailer chain selections have to be separated by commas" + bcolors.ENDC
+            print(bcolors.RED + "ERROR - remailer chain selections have to be separated by commas" + bcolors.ENDC)
             pressKey()
             return
     a = chain.split(',')
     for n in a:
         if not n.isdigit():
-            print bcolors.RED + "ERROR - remailer chain selection cannot contains non-numeric chars" + bcolors.ENDC
+            print(bcolors.RED + "ERROR - remailer chain selection cannot contains non-numeric chars" + bcolors.ENDC)
             return
         n = int(n)
         n -= 1
@@ -360,11 +362,11 @@ def validateChain(chain):
 
     # check if last remailer is middleman
     if checkMiddle(remailer_chain[len(remailer_chain) - 1]):
-        print bcolors.RED + "ERROR - remailer %s is middleman, it cannot be last remailer in chain" % remailer_chain[len(remailer_chain)-1] + bcolors.ENDC
+        print(bcolors.RED + "ERROR - remailer %s is middleman, it cannot be last remailer in chain" % remailer_chain[len(remailer_chain)-1] + bcolors.ENDC)
         pressKey()
         chooseChain()
     if checkBrokenChains(remailer_chain):
-        print bcolors.RED + "ERROR - broken chain selected, check the breaks in stats last column" + bcolors.ENDC
+        print(bcolors.RED + "ERROR - broken chain selected, check the breaks in stats last column" + bcolors.ENDC)
         pressKey()
         chooseChain()
 
@@ -397,7 +399,7 @@ def main():
         config['last_message'] = "OK, initial check passed"
 
     if not nyms.sections:
-        print "No nyms configured, going to create it..."
+        print("No nyms configured, going to create it...")
         createNym()
     else:
         setActiveNym(nyms.sections[0])
@@ -409,25 +411,25 @@ def main():
     try:
         if opts.test:
             if config['options']['testnym'] == "":
-                print bcolors.RED + "\nTestnym not configured in config.ini, exiting..." + bcolors.ENDC
+                print(bcolors.RED + "\nTestnym not configured in config.ini, exiting..." + bcolors.ENDC)
                 sys.exit()
             else:
                 setActiveNym(config['options']['testnym'])
                 parse_stats()
                 writeMessage(subject="nymphet test", recipient=config['options']['testnym_recipient'], text="nymphet test", test=1)
-                print bcolors.GREEN + "\nTest message sent from nym %s to %s" % (config['options']['testnym'], config['options']['testnym_recipient'])
+                print(bcolors.GREEN + "\nTest message sent from nym %s to %s" % (config['options']['testnym'], config['options']['testnym_recipient']))
         else:
             parse_stats()
             menu()
 
     except KeyboardInterrupt:
-        print "program terminated"
+        print("program terminated")
     except SystemExit:
-        print "program terminated, bye"
+        print("program terminated, bye")
     except:
-        print bcolors.RED + "\nAn unhandled exception occured, here's the traceback!\n" + bcolors.ENDC
+        print(bcolors.RED + "\nAn unhandled exception occured, here's the traceback!\n" + bcolors.ENDC)
         traceback.print_exc()
-        print bcolors.RED + "\nReport this to putro@autistici.org" + bcolors.ENDC
+        print(bcolors.RED + "\nReport this to putro@autistici.org" + bcolors.ENDC)
         sys.exit()
 
 if __name__ == '__main__':
diff --git a/checks.py b/checks.py
index 8b52876a3f8671ab2c2d620e4ce2b7194d53c27f..bb5cafec6d8f5682fe5c75a9dcbf65e845e9fafa 100644
--- a/checks.py
+++ b/checks.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import os
 import sys
@@ -21,8 +21,7 @@ def checkAscii(file):
             l = f.readline()
         except:
             num = i + 1
-            print "config file problem (%s): line %d contains non-ascii " \
-                  "character, fix it" % (file, num)
+            print("config file problem (%s): line %d contains non-ascii character, fix it" % (file, num))
             bad = 1
             break
     f.close()
@@ -33,8 +32,9 @@ def OptionsCheck(config):
     """ performs some checks """
     try:
         f = open(os.path.dirname(sys.argv[0]) + "/check", "w")
-    except:
-        print "Error: you cannot write here, fix permission"
+    except Exception as e:
+        print(e)
+        print("Error: you cannot write here, fix permission")
         sys.exit()
     else:
         f.close()
@@ -42,8 +42,10 @@ def OptionsCheck(config):
 
     try:
         download(config['stats']['stats_mlist'], config)
-    except:
-        print "Error: cannot download fresh remailer stats"
+    except Exception as e:
+        print(e)
+        print("Error: cannot download fresh remailer stats")
+        sys.exit()
 
     try:
         mix = subprocess.Popen(config['options']['mixmaster'],
@@ -51,4 +53,4 @@ def OptionsCheck(config):
     except OSError:     # usally means that mixmaster could not be executed
         raise MixError('Could not find mixmaster binary.')
 
-    return True
\ No newline at end of file
+    return True
diff --git a/config.ini.sample b/config.ini.sample
index 805d0a8955582fc7548695ae46db72ddd53985df..580e0aa2f55b31866d49dd15dc6dcb6a26cda95c 100644
--- a/config.ini.sample
+++ b/config.ini.sample
@@ -11,8 +11,7 @@ testnym_recipient = ""
 
 [stats]
 # set parameters fow remailer stats, change with your favourite pinger
-#stats_url = https://remailer.paranoici.org/stats/
-stats_url = http://brabus.remailer.org.uk/echolot/
+stats_url = https://www.mixmin.net/echolot/
 
 stats_mlist = mlist2.txt
 allow_from = from.html
diff --git a/config.py b/config.py
index 623069a5f60006771279b25c7588a62c18cbd249..4029b29a3ba9308622dbf5fd86ce969e6cedb210 100644
--- a/config.py
+++ b/config.py
@@ -11,8 +11,8 @@ configfile = os.path.dirname(sys.argv[0]) + "/config.ini"
 
 try:
     config = ConfigObj(configfile, file_error=True)
-except (ConfigObjError, IOError), e:
-    print 'Could not read "%s": %s' % (configfile, e)
+except (ConfigObjError, IOError) as e:
+    print('Could not read "%s": %s' % (configfile, e))
     sys.exit(-1)
 
 
@@ -54,7 +54,7 @@ def printNymList():
     nymlist = nymList()
     counter = 0
     for n in nymlist:
-        print counter, "-", n
+        print(counter, "-", n)
         counter += 1
     return counter
 
diff --git a/gpgfuncts.py b/gpgfuncts.py
index f6994864e2abda9353c57ab47dfc043c2fe8cdfc..7191f4492f3571dd492e9f3237cd97629a5a6e1e 100644
--- a/gpgfuncts.py
+++ b/gpgfuncts.py
@@ -10,7 +10,7 @@ try:
     global gpg
     gpg = gnupg.GPG()
 except:
-    print "Error, problems with your keyring directory, exiting"
+    print("Error, problems with your keyring directory, exiting")
     sys.exit(0)
 
 
@@ -21,11 +21,11 @@ def createKey(email, name, comment="", key_type="RSA", key_length=4096):
         pwd2 = getpass.getpass("type again the password: ")
         if pwd == pwd2:
             break
-    print "wait, I'm generating the key, move the mouse, " \
-            "press keys, it could take some times......\n"
+    print("wait, I'm generating the key, move the mouse, " \
+          "press keys, it could take some times......\n")
     input_data = gpg.gen_key_input(name_real=name, name_email=email,
-        name_comment="", passphrase=pwd, key_type=key_type,
-        key_length=key_length, )
+                                   name_comment="", passphrase=pwd, key_type=key_type,
+                                   key_length=key_length, )
     key = gpg.gen_key(input_data)
 
 
@@ -46,10 +46,10 @@ def selectKey(email, secret=False):
             if m:
                 """check if key is valid"""
                 if encrypt("test", k["fingerprint"],
-                    test=True).status == "encryption ok":
+                           test=True).status == "encryption ok":
                     key = True
                     config['last_message'] = "OK - key choosed: keyID=%s" \
-                    % getKeyID(k["fingerprint"])
+                                             % getKeyID(k["fingerprint"])
                     break
 
                 else:
@@ -60,7 +60,7 @@ def selectKey(email, secret=False):
             break
     if not key:
         config['last_message'] = "ERROR, public key for %s NOT found" % email
-        print "ERROR, public key for %s NOT found" % email
+        print("ERROR, public key for %s NOT found" % email)
         pressKey()
         return False
     return k["fingerprint"]
@@ -72,8 +72,8 @@ def listSecKeys():
     counter = 0
     for k in seckeys:
         counter += 1
-        print "%s - %s - %s" % (counter, k["uids"][0], k["keyid"])
-        print [x for x in k["uids"]]
+        print("%s - %s - %s" % (counter, k["uids"][0], k["keyid"]))
+        print([x for x in k["uids"]])
     return seckeys
 
 
@@ -125,22 +125,22 @@ def defineSecKey():
     """ Select which secret key to use """
     ls = listSecKeys()
     numkeys = int(len(ls))
-    print "there are %s keys" % numkeys
+    print("there are %s keys" % numkeys)
     if numkeys == 0:
-        print "going to generate a new key..."
+        print("going to generate a new key...")
         createKey()
         listSecKeys()
 
     while True:
-        a = raw_input("enter key number (and press enter): ")
+        a = input("enter key number (and press enter): ")
         if a.isdigit():
             a = int(a)
             if a < 1:
-                print "you can't enter a key number lower than 1"
+                print("you can't enter a key number lower than 1")
                 continue
             elif a > numkeys:
-                print "there are only %d keys, select key number again" \
-                % numkeys
+                print("there are only %d keys, select key number again" \
+                      % numkeys)
                 continue
             break
     a -= 1
@@ -166,13 +166,13 @@ def stripVersion(pgptext):
 def encrypt(message, recipient, sign=False, passphrase=False, test=False):
     """ Encrypt a message for a recipient """
     encrypted_ascii_data = gpg.encrypt(message, recipient, always_trust=True,
-                                    sign=sign, passphrase=passphrase)
+                                       sign=sign, passphrase=passphrase)
     if not test:
         if encrypted_ascii_data.status != "encryption ok":
             config['last_message'] = "ERROR " + encrypted_ascii_data.status + \
-            " (recipient: %s)" % recipient
+                                     " (recipient: %s)" % recipient
             return "ERROR"
         else:
             return stripVersion(str(encrypted_ascii_data))
     else:
-        return encrypted_ascii_data
\ No newline at end of file
+        return encrypted_ascii_data
diff --git a/stats.py b/stats.py
index f8cbeee7c83ae93cc76c60c76e478c53b35ccf00..02c050029d959994fb37da732e3d56e7fcc8e1ea 100644
--- a/stats.py
+++ b/stats.py
@@ -146,8 +146,8 @@ def format_stats(name):
 
 
 def uptime_sort_m():
-    remailers = stats_m.keys()
-    remailers.sort(cmp=lambda x,y: cmp(stats_m[y].uptime, stats_m[x].uptime))
+    remailers = list(stats_m.keys())
+    sorted(remailers) # python3: remailers.sort(cmp=lambda x,y: cmp(stats_m[y].uptime, stats_m[x].uptime))
     n = 1
     for r in remailers:
         stats_m[r].number = str(n)
diff --git a/utils.py b/utils.py
index ce9c74d39334f1762ae15a511af119e3234f80ac..defa9cf1e7ac4692b5e8dcce9340892661b78bd0 100644
--- a/utils.py
+++ b/utils.py
@@ -10,31 +10,20 @@ class InputError(Exception):
 
 def download(file, config):
     """ Download remailer stats file """
-    print "downloading %s....... please wait" % file
-    from urllib2 import Request, urlopen, URLError, HTTPError
+    print("downloading %s....... please wait" % file)
+    import urllib.request
     url = config['stats']['stats_url'] + file
-    req = Request(url)
     try:
-        response = urlopen(req)
-    except HTTPError, e:
-        print 'Error - The server couldn\'t fulfill the request.'
-        print 'Error code: ', e.code
+        urllib.request.urlretrieve(url, os.path.dirname(sys.argv[0]) + "/" + file)
+    except Exception as e:
+        print('Error downloading file.')
+        print('Reason: ', e)
         pressKey()
-    except URLError, e:
-        print 'Error - We failed to reach a server.'
-        print 'Reason: ', e.reason
-        pressKey()
-    else:
-        the_page = response.read()
-        w = open(os.path.dirname(sys.argv[0]) + "/" + file, "w")
-        w.write(the_page)
-        w.close()
-        pass
 
 
 def pressKey():
     """ wait user to press RETURN """
-    raw_input("press RETURN to continue\n")
+    input("press RETURN to continue\n")
 
 
 def validateEmail(email):
@@ -49,13 +38,13 @@ def validateChoice(choice, list):
     try:
         i = (int(choice))
     except ValueError:
-        print "Invalid input, enter a number...."
+        print("Invalid input, enter a number....")
         return False
     if i < 1:
-        print "enter a number greater than 1...."
+        print("enter a number greater than 1....")
         return False
     if i > len(list):
-        print "error, there are only %s choices" % len(list)
+        print("error, there are only %s choices" % len(list))
         return False
     else:
         return True
@@ -68,12 +57,12 @@ def askPassphrase():
 
 
 def askSomething(question):
-    usr_input = raw_input(question)
+    usr_input = input(question)
     return usr_input
 
 
 def askYesNo(question, default="yes"):
-    """Ask a yes/no question via raw_input() and return their answer.
+    """Ask a yes/no question via input() and return their answer.
 
     "question" is a string that is presented to the user.
     "default" is the presumed answer if the user just hits <Enter>.
@@ -82,8 +71,8 @@ def askYesNo(question, default="yes"):
 
     The "answer" return value is one of "yes" or "no".
     """
-    valid = {"yes":True,   "y":True,  "ye":True,
-             "no":False,     "n":False}
+    valid = {"yes": True,   "y": True,  "ye": True,
+             "no": False,     "n": False}
     if default is None:
         prompt = " [y/n] "
     elif default == "yes":
@@ -95,7 +84,7 @@ def askYesNo(question, default="yes"):
 
     while True:
         sys.stdout.write(question + prompt)
-        choice = raw_input().lower()
+        choice = input().lower()
         if default is not None and choice == '':
             return valid[default]
         elif choice in valid:
@@ -108,7 +97,7 @@ def askYesNo(question, default="yes"):
 def printList(list):
     counter = 1
     for i in list:
-        print counter, "-", i
+        print(counter, "-", i)
         counter += 1
 
 
@@ -119,17 +108,17 @@ def chooseList(list):
         try:
             usr_input = input("Enter your choice (1-%s): " % len(list))
         except:
-            print "\nError - you have to enter a number !!!!"
+            print("\nError - you have to enter a number !!!!")
     return list[usr_input - 1]
 
 
 def selectServer(config):
     servers = config['options']['nymservers']
     for idx, val in enumerate(servers):
-        print idx + 1, val
+        print(idx + 1, val)
 
     while True:
-        choice = raw_input("Enter the nymserver you want to use: ")
+        choice = input("Enter the nymserver you want to use: ")
         if validateChoice(choice, servers):
             break
 
@@ -140,10 +129,10 @@ def selectServer(config):
 def chooseSubjType(config):
     subject_types = config['options']['subj_types']
     for idx, val in enumerate(subject_types):
-        print idx + 1, "-", val
+        print(idx + 1, "-", val)
 
     while True:
-        choice = raw_input("Enter what kind of subject you want: ")
+        choice = input("Enter what kind of subject you want: ")
         if validateChoice(choice, subject_types):
             break
 
@@ -159,7 +148,7 @@ def getDomain(email):
 def isGpg(message):
     m = re.compile('^-----BEGIN PGP MESSAGE-----')
     line = message.split("\n", 1)[0]
-    print line
+    print(line)
     pressKey()
     if m.match(line):
         return True