CHA — Cursor horizontal absolute (column)
Move the cursor to column N of the current row (1-indexed).
Byte forms
Every common string-literal form so you can paste-and-search either direction.
\x1b[NG\033[1G\e[1GESC [ N G1b 5b <N> 47Description
ECMA-48 §8.3.9 — Cursor Horizontal Absolute (CHA). Final byte G, byte sequence \x1b[<N>G where N is the 1-based column. Sets the column without touching the row; N defaults to 1 if omitted (\x1b[G = "move to column 1"). The horizontal-only counterpart of VPA (\x1b[<N>d, vertical position absolute) and the column half of CUP (\x1b[<r>;<c>H, full row+column). The most common idiom is \x1b[1G\x1b[K (jump to column 1 + erase to end of line) — visually equivalent to \r\x1b[K on a CRLF terminal but with no line-feed semantics, which matters when the writer sits inside a DECSTBM scroll region or a noecho raw-mode TTY where \r could be interpreted unexpectedly.
Portability — universal. xterm, iTerm2, kitty, alacritty, wezterm, gnome-terminal, Konsole, Ghostty, Windows Terminal, ConPTY 1809+, and Linux console all support CHA. HPA (\x1b[<N>\, final byte 0x60 backtick) is the ECMA-48 §8.3.57 synonym with identical semantics — every terminal that accepts one accepts the other. Out-of-range column values clamp to the rightmost visible column (or the rightmost column of the DECSLRM left/right margin region when that's active on a margin-supporting emulator). The universal stumble is 1-based vs 0-based indexing: column 1 is the leftmost, not column 0. In xterm and most modern emulators \x1b[0G is treated as \x1b[1G because parameter 0` is interpreted as "use default" and the default for CHA is 1 — but relying on that is fragile, the spec-correct value for the leftmost column is 1. tmux passes CHA through unmodified.
No "close" — CHA is a stateless move, not a toggle. The redraw idiom is \x1b[1G\x1b[K<text>; for in-place spinners and progress bars, \x1b[<col>G positions at a known column and the writer follows up with text. Prefer CHA over \r when carriage returns might be filtered (cooked-mode TTYs that translate \r to CRLF, or a TUI that tracks column position independently of the terminal's own CR handling) and when you want the move to be visible to a parser that doesn't special-case \r. For absolute targeting where the row also matters, CUP (cursor-position, \x1b[r;cH) is one round-trip cheaper than CHA + VPA. Related: cursor-position (CUP — absolute row+column in one move), cursor-next-prev-line (CNL / CPL — vertical move that also forces column 1), erase-line (EL — partial / entire line erase, the natural pairing for redraw loops).
Spec citation: ECMA-48 §8.3.9 (CHA)
Examples
printf 'progress:\033[20G50%%\033[1G' print('\x1b[20G50%')fmt.Print("\x1b[20G50%")process.stdout.write('\x1b[20G50%')printf("\x1b[20G50%%");Used in
Real-world tools that emit this sequence — anchors the bytes to commands you've already used.
- tqdm, pip, npm download progress barsrate / ETA / percentage are positioned at fixed columns with `\x1b[<col>G` so the layout stays aligned regardless of file-name length
- starship, oh-my-zsh, powerlevel10k right-promptsright-aligned segments compute `COLUMNS - len(content)` then emit CHA to jump to that column before writing
- git rebase --interactive editor screensuses CHA + EL combos to redraw the highlighted commit line in place without disturbing surrounding context
- whiptail, dialog (TUI form widgets)every form field places its label and input box at predetermined columns via CHA
- fzf — search-result preview pane positions matched highlights via CHA before underlining the substring
Frequently asked
Short answers to the questions developers actually search for this sequence.
- Why does
\x1b[0Gend up at column 1 instead of column 0? - Because CHA is 1-based — column 1 is the leftmost cell, there is no column 0. ECMA-48 §5.4 specifies that an SGR / cursor-positioning parameter value of 0 means "use the default", and the default for CHA is 1. So
\x1b[0G,\x1b[1G, and\x1b[G(omitted) all land at the leftmost column. Spec-correct code emits\x1b[1G; relying on the0→1coercion works on xterm and every mainstream emulator but is undefined behaviour and will trip up strict parsers (some ECMA-48 conformance test suites flag it). - When should I use
\x1b[1Ginstead of\rto return to column 1? - Three situations. (1) Raw-mode TTY where
OPOST/onlcris off —\rthen has no special meaning the line discipline can mangle (it'd be passed through anyway, but you avoid surprise interaction with custom termios flags). (2) Inside a DECSTBM scroll region where you want column 1 of the *current* row without risking implicit scrolling — CHA is a pure column move,\r\nis two operations and the\npart may scroll. (3) When a parser downstream (a recorder, terminal-output linter, escape-aware paginator) doesn't special-case\r— emitting CHA makes the intent explicit as a CSI sequence. For ordinary cooked-mode shell output,\ris fine and byte-shorter; reach for\x1b[1Gonly when one of these matters.
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
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes |
Related sequences
In the family cookbook
CSI cookbook · 2. Cursor movement — CUU / CUD / CUF / CUB + CUP + CHA / VPA