Skip to main content
ansicode

C0 controls — BS, HT, LF, CR, BEL (single-byte codes)

The single-byte C0 control characters that move the cursor or signal events — no ESC introducer needed.

Byte forms

Every common string-literal form so you can paste-and-search either direction.

\\x1b[\x08 BS \x09 HT \x0a LF \x0d CR \x07 BEL
\\033[\010 / \011 / \012 / \015 / \007
\\e[\b / \t / \n / \r / \a
ESC [BS / HT / LF / CR / BEL
hex08 / 09 / 0a / 0d / 07

Description

These five single-byte controls predate ANSI/VT and are still acted on by every terminal: BS (0x08, \b) moves the cursor one cell left (does NOT erase — pair with a space + BS again to erase, or use EL). HT (0x09, \t) advances the cursor to the next tab stop (default every 8 columns). LF (0x0a, \n) moves down one line (and, with onlcr tty mode, returns to column 1 — Unix shells rely on this, which is why a raw \n looks ladder-stepped under stty -onlcr). CR (0x0d, \r) returns to column 1 of the current line — used for progress bars (\r + redraw). BEL (0x07, \a) rings the audible bell or flashes the visual bell depending on the terminal's setting; it also serves as the de-facto OSC string terminator (see OSC 0/2 and OSC 8). None of these consume an ESC byte — they are part of the C0 control set inherited from ASCII (1963) / ECMA-6.

Spec citation: ECMA-48 §8.2 (C0 set) / ASCII / ECMA-6

Parameters

BS (0x08)backspace — cursor left 1
HT (0x09)horizontal tab — to next tab stop
LF (0x0a)line feed — down 1 line
CR (0x0d)carriage return — to column 1
BEL (0x07)bell — audible/visual alert; OSC terminator

Examples

bash
printf '\rprogress: 50%%\r'   # CR redraws current line\nprintf 'beep\a\n'           # BEL rings the bell
python
import sys, time\nfor i in range(101):\n  sys.stdout.write(f'\r{i}%'); sys.stdout.flush(); time.sleep(0.02)
go
fmt.Print("\rprogress: 50%\r")
javascript
process.stdout.write('\rprogress: 50%\r')
c
printf("\rprogress: 50%%\r");

Used in

Real-world tools that emit this sequence — anchors the bytes to commands you've already used.

  • npm, pnpm, pip, cargo progress barsevery progress tick emits `\r` to redraw the line in place — universal across language package managers
  • tput bel, printf '\a'shell scripts ring the system bell on errors or completion notifications
  • readline, GNU bash, zsh line editor`\b` (BS) backspaces in cooked-mode editing; cooked-mode `\n` translated to `\r\n` via `onlcr`
  • column, expand, cat -T`\t` (HT) is the table-cell separator everything in coreutils parses against
  • asciinema, script — record the raw byte stream including all C0 controls

Frequently asked

Short answers to the questions developers actually search for this sequence.

How do I make \a (BEL) flash the screen instead of beeping audibly?
It's a terminal preference, not a sequence change — \x07 (BEL) is dispatched by the emulator, which then decides whether to ring the system bell or flash the window. xterm has bellIsUrgent + visualBell X resources, iTerm2 ships a per-profile *Visual bell* toggle, Windows Terminal exposes bellStyle: "visual" in settings.json, gnome-terminal / Konsole have a *Visual bell* checkbox in the profile dialog, and kitty / wezterm / alacritty all expose enable_audio_bell / audible-bell. Apps that need to *force* a flash regardless of terminal config can emit \x1b[?5h\x1b[?5l (DECSCNM on/off — the screen-reverse mode), which most emulators render as a single-frame visual flash.
Why does \r work as \r\n from my code but stays a bare carriage return in raw-mode?
POSIX terminals interpose an onlcr / opost translation in the tty line discipline — when output processing is on (the default for cooked mode), a lone \n is rewritten as \r\n before reaching the emulator. stty raw (or any TUI calling cfmakeraw()) clears OPOST, so your bytes hit the terminal verbatim: \n then becomes a pure line-feed (cursor down, column unchanged) and you must emit \r yourself to return to column 1. This is why progress-bar loops written for raw-mode TUIs explicitly use \r (or \x1b[1G, see cursor-column) instead of relying on \n. The reverse symptom — ladder-stepped output under stty -onlcr — is the same root cause.

Terminal support

xterm
yes
Linux console (fbcon)
yes
macOS Terminal.app
yes
iTerm2
yes
Windows Terminal
yes
cmd.exe / ConPTY
yes
kitty
yes
alacritty
yes
WezTerm
yes
Ghostty
yes
GNOME Terminal
yes
Konsole
yes
tmux
yes
GNU screen
yes

Related sequences

In the family cookbook

C0 cookbook · 1. CR + LF — the line-ending pair