Masking user input in python with asterisks

39,564

Solution 1

Depending on the OS, how you get a single character from user input and how to check for the carriage return will be different.

See this post: Python read a single character from the user

On OSX, for example, you could so something like this:

import sys, tty, termios

def getch():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(sys.stdin.fileno())
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

key = ""
sys.stdout.write('Password :: ')
while True:
    ch = getch()
    if ch == '\r':
        break
    key += ch
    sys.stdout.write('*')
print
print key

Solution 2

If you want a solution that works on Windows/macOS/Linux and on Python 2 & 3, you can install the pwinput module:

pip install pwinput

Unlike getpass.getpass() (which is in the Python Standard Library), the pwinput module can display *** mask characters as you type.

Example usage:

>>> pwinput.pwinput()
Password: *********
'swordfish'
>>> pwinput.pwinput(mask='X') # Change the mask character.
Password: XXXXXXXXX
'swordfish'
>>> pwinput.pwinput(prompt='PW: ', mask='*') # Change the prompt.
PW: *********
'swordfish'
>>> pwinput.pwinput(mask='') # Don't display anything.
Password:
'swordfish'

Unfortunately this module, like Python's built-in getpass module, doesn't work in IDLE or Jupyter Notebook.

More details at https://pypi.org/project/pwinput/

Note that pwinput is the new name for the stdiomask module.

Solution 3

Disclaimer: does not provide the asterix in terminal, but it does so in jupyter notebook.

The below code provides replaces written characters with asterix and allow for deletion of wrongly typed characters. The number of asterixes reflects the number of typed characters.

import getpass
key = getpass.getpass('Password :: ')

enter image description here

And after the user press enter:

enter image description here

Solution 4

To solve this I wrote this small module pyssword to mask the user input password at the prompt. It works with windows. The code is below:

from msvcrt import getch
import getpass, sys

def pyssword(prompt='Password: '):
    '''
        Prompt for a password and masks the input.
        Returns:
            the value entered by the user.
    '''

    if sys.stdin is not sys.__stdin__:
        pwd = getpass.getpass(prompt)
        return pwd
    else:
        pwd = ""        
        sys.stdout.write(prompt)
        sys.stdout.flush()        
        while True:
            key = ord(getch())
            if key == 13: #Return Key
                sys.stdout.write('\n')
                return pwd
                break
            if key == 8: #Backspace key
                if len(pwd) > 0:
                    # Erases previous character.
                    sys.stdout.write('\b' + ' ' + '\b')                
                    sys.stdout.flush()
                    pwd = pwd[:-1]                    
            else:
                # Masks user input.
                char = chr(key)
                sys.stdout.write('*')
                sys.stdout.flush()                
                pwd = pwd + char
Share:
39,564
Jackson Blankenship
Author by

Jackson Blankenship

Updated on October 28, 2021

Comments

  • Jackson Blankenship
    Jackson Blankenship over 2 years

    I am trying to mask what the user types into IDLE with asterisks so people around them can't see what they're typing/have typed in. I'm using basic raw input to collect what they type.

    key = raw_input('Password :: ')
    

    Ideal IDLE prompt after user types password:

    Password :: **********
    
  • Ahmad F
    Ahmad F about 6 years
    Although your code snippet might solve the issue, you should describe what’s the purpose of your code (how it solves the problem). Furthermore, you might want to check stackoverflow.com/help/how-to-answer
  • Stevoisiak
    Stevoisiak about 5 years
    When run on a terminal or command line, getpass hides the input completely. No asterisks are displayed.
  • Stevoisiak
    Stevoisiak about 5 years
    Has this been tested on Linux/MacOS?
  • Rich Sadowsky
    Rich Sadowsky over 4 years
    this didn't work for me with PyCharm Console with Python 3.7, but neither does getpass.getpass. Both just use something like input. This appears to be a PyCharm limitation and not a problem with your library.
  • QHarr
    QHarr about 4 years
    Is there a way to get this to work in Jupyter notebook please?
  • Al Sweigart
    Al Sweigart about 4 years
    Unfortunately it's not possible to get it working in Jupyter notebook. It's very much tied to command line/terminal windows, so a system that works in a browser (like Jupyter) or provides it's own text output screen (like VS Code) won't execute the terminal control codes that erase text the way a command line window would.
  • QHarr
    QHarr about 4 years
    Thanks. Seems same problem for IDLE where it echoes and displays password.
  • Al Sweigart
    Al Sweigart over 2 years
    Minor note: stdiomask is now called pwinput. You would run import pwinput and then call pwinput.pwinput()