Searches like golang read password from stdin, golang.org/x/term readpassword example, pkg.go.dev golang.org/x/term readpassword isterminal, and golang.org/x/term readpassword windows usually point to the same API: term.ReadPassword from golang.org/x/term. The upstream doc string states it reads a line of input from a terminal without local echo and that the returned slice does not include \n. Queries such as pkg.go.dev golang.org/x/term readpassword and golang.org/x/term readpassword platforms are really about that contract: you must pass a terminal file descriptor, not only pick Windows versus Linux.
What ranking tutorials and issues usually add beyond a one-line example: guard with term.IsTerminal, print your own newline after ReadPassword (Enter does not produce a visible line break), and branch when stdin is a pipe—see for example Cesar Gimenes on capturing terminal passwords in Go and ataraskov.dev on pipes and passwords; the historical discussion in golang/go#19909 explains why redirected stdin breaks naive ReadPassword use.
Tested with Go 1.24 on Linux (build and local TTY run;
ReadPasswordneeds an interactive terminal).
Install golang.org/x/term
From a module:
go get golang.org/x/term@latestMinimal ReadPassword example (os.Stdin.Fd)
The signature is func ReadPassword(fd int) ([]byte, error). Passing int(os.Stdin.Fd()) matches the package examples and avoids assuming descriptor 0 on every platform (the term package header calls this out for non-Unix systems). On Linux, syscall.Stdin is typically 0 and matches stdin as well—queries like golang.org/x/term readpassword example syscall.stdin are about that constant—but os.Stdin remains the portable handle.
package main
import (
"fmt"
"os"
"golang.org/x/term"
)
func main() {
fd := int(os.Stdin.Fd())
if !term.IsTerminal(fd) {
fmt.Fprintln(os.Stderr, "stdin is not a terminal; cannot use ReadPassword here")
os.Exit(1)
}
fmt.Print("Password: ")
pw, err := term.ReadPassword(fd)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Println() // ReadPassword does not emit a newline after Enter
fmt.Printf("read %d bytes (secret not printed)\n", len(pw))
}Run with go run . in a real terminal (not an IDE “Run” pane without a TTY). You type blind; after Enter, the program prints a blank line then the length line.
IsTerminal, pipes, and platforms
pkg.go.dev golang.org/x/term readpassword isterminal and golang.org/x/term readpassword isterminal platforms boil down to: call term.IsTerminal(fd) on the same fd you pass to ReadPassword. If it is false, fall back—for example read a line with bufio when a script pipes a secret—so CI and non-interactive runners do not see inappropriate ioctl for device.
Optional: hash with bcrypt after reading
Hashing is separate from hiding input. After you have []byte from ReadPassword, you can hash with bcrypt.GenerateFromPassword. Prefer bcrypt.DefaultCost (or a documented cost) rather than an extreme value that slows legitimate logins.
import "golang.org/x/crypto/bcrypt"
hash, err := bcrypt.GenerateFromPassword(pw, bcrypt.DefaultCost)Compare later with bcrypt.CompareHashAndPassword.
Golang asterisk masking (not ReadPassword)
ReadPassword implements no-echo reading, not per-character * display (golang asterisk). Masked echo usually means raw terminal mode plus manual drawing, or a TUI library. For most CLIs, silent ReadPassword is the idiomatic choice.
Summary
golang read password from stdin in production Go code is usually term.ReadPassword(int(os.Stdin.Fd())) together with term.IsTerminal, an explicit newline, and a non-TTY fallback—patterns repeated across official comments, pkg.go.dev golang.org/x/term readpassword documentation, and high-ranking community posts. golang.org/x/term readpassword windows and Unix both go through the same API; golang.org/x/term readpassword example os.stdin.fd is the portable FD choice, while syscall.Stdin is mostly a Linux shortcut. Separate bcrypt (or another KDF) from the capture step, and treat golang asterisk masking as a different feature than ReadPassword.
References
term.ReadPasswordandterm.IsTerminal(pkg.go.dev)- Source:
ReadPassworddoc comment bcryptpackage- Community: terminal passwords and
IsTerminal(Cesar Gimenes) - Community: pipes vs TTY for secrets (ataraskov.dev)
- Issue discussion: non-terminal stdin and
ReadPassword
Frequently Asked Questions
1. What does pkg.go.dev say golang.org/x/term ReadPassword does?
term package).2. Should I use syscall.Stdin or os.Stdin.Fd() with ReadPassword?
syscall.Stdin is often 0 and matches stdin’s descriptor, but the term package documentation notes that on some systems stdin’s FD is not necessarily 0; prefer int(os.Stdin.Fd()) for the value you pass to ReadPassword and IsTerminal.3. Why check term.IsTerminal before ReadPassword?
4. Does golang.org/x/term ReadPassword work on Windows?
golang.org/x/term module implements terminal helpers for Windows as well as Unix; still use int(os.Stdin.Fd()) and handle non-interactive stdin the same way you would on Linux.5. Is golang asterisk masking the same as ReadPassword?
ReadPassword turns echo off entirely; showing * per keystroke is a different UI pattern, usually from a TUI library or custom raw-mode reader, not from ReadPassword alone.
