SGR 38;2;R;G;B — 24-bit truecolor foreground
Pick any of 16,777,216 foreground RGB colors directly.
Byte forms
Every common string-literal form so you can paste-and-search either direction.
\x1b[38;2;R;G;Bm\033[38;2;R;G;Bm\e[38;2;R;G;BmESC [ 3 8 ; 2 ; R ; G ; B m1b 5b 33 38 3b 32 3b ... 6dLive preview
Rendered in your browser via the same tokeniser the decoder uses — no terminal needed.
Description
SGR 38;2;R;G;B picks any of 16,777,216 foreground RGB colours directly — R, G, B each take 0–255. The background equivalent is \x1b[48;2;R;G;Bm. The shape comes from ITU-T T.416 ('Direct color'), adopted by xterm-ctlseqs as the de-facto truecolor SGR. Most parsers accept either the semicolon form (xterm legacy, widely supported) or the ECMA-48-compliant colon form \x1b[38:2::R:G:Bm — note the empty 4th sub-parameter, which T.416 reserves for a colorspace identifier. Emit semicolons by default; the colon form is safer only when you've verified the consumer handles it (some libraries reject the empty sub-param). Unlike SGR 30–37, the rendered colour is exactly the RGB you specified — not theme-dependent — which is the whole point of using truecolor.
Truecolor is the portability fault line in 2026. The detection signal apps should check is $COLORTERM=truecolor (or 24bit); without it, fall back to 256-palette quantization or to the basic 16, because not every stack renders the 24-bit bytes. Concrete pitfalls: (1) xterm parses 24-bit SGR unconditionally but doesn't export $COLORTERM=truecolor — libraries (chalk, colorama, click) that gate on the env var silently downgrade to 256-colour on xterm even though xterm itself accepts the bytes; (2) Apple Terminal.app has rendered truecolor since 10.7 Lion (2011) but also doesn't set $COLORTERM, with the same downgrade — set it manually in your shell init since the preference panel has no toggle; (3) tmux quantizes truecolor to 256-palette unless you add set -g default-terminal "tmux-256color" + set -ga terminal-overrides ",*256col*:Tc" (or the newer ,*:RGB) to ~/.tmux.conf; (4) Linux console / fbcon and Windows conhost.exe both quantize to 16; (5) GNU screen older than 5.0.0 (April 2024) silently quantizes — Ubuntu 22.04 ships 4.09, Apple's /usr/bin/screen ships v4.00.03 from 2006. Detection wrap-up: $COLORTERM=truecolor + infocmp $TERM | grep -E '(Tc|RGB)' is the safest test before emitting (see truecolor-detect).
Disable foreground with \x1b[39m — restores terminal default without touching background or attributes. The surgical close pair is \x1b[38;2;R;G;Bm…\x1b[39m; reaching for \x1b[0m clobbers everything else you set, and skipping the reset altogether bleeds colour into the user's prompt (see color-bleed). For an indexed palette that survives more multiplexer hops without quantization, see sgr-fg-256; for the 16 basic slots that render everywhere from Linux console to legacy conhost, see sgr-fg-basic; for the matching background side, see sgr-bg-truecolor. Truecolor is the right default on modern terminals (iTerm2, kitty, alacritty, wezterm, ghostty, Windows Terminal, recent gnome-terminal / konsole) but always pair it with the $COLORTERM check so the fallback path doesn't ship broken on stacks that quantize.
Spec citation: ITU-T T.416 / xterm-ctlseqs (Direct color)
Examples
printf '\033[38;2;255;128;0morange\033[0m\n'print('\x1b[38;2;255;128;0morange\x1b[0m')fmt.Print("\x1b[38;2;255;128;0morange\x1b[0m\n")console.log('\x1b[38;2;255;128;0morange\x1b[0m')printf("\x1b[38;2;255;128;0morange\x1b[0m\n");Used in
Real-world tools that emit this sequence — anchors the bytes to commands you've already used.
- bat, delta (TrueColor themes)modern syntax themes assume 24-bit colour — fall back gracelessly without it
- gh (GitHub CLI) — branded reds and greens
- vim, neovim with `set termguicolors`switches all highlight groups from cterm to gui 24-bit colours
- starship — branded prompt segments
Frequently asked
Short answers to the questions developers actually search for this sequence.
- How do I detect whether the terminal supports 24-bit truecolor?
- Check
$COLORTERM— when set totruecoloror24bit, the terminal advertises full 24-bit support.$TERMcontaining-direct(e.g.xterm-direct,tmux-direct) is the terminfo-side signal. When neither is set, fall back to 256-colour (\x1b[38;5;Nm) or the basic 16-colour palette. See thetruecolor-detectpitfall. - Should I use
;or:between the38;2parameters? - Both work on most modern terminals.
\x1b[38;2;255;100;50m(semicolons) is the xterm-style flat parameter list and is universally understood.\x1b[38:2::255:100:50m(colons with the colour-space slot) is the ITU T.416 / ECMA-48 sub-parameter form — kitty, alacritty, wezterm, ghostty accept it; older terminals do not. Prefer semicolons for portability. - Why do my smooth gradients look banded on macOS Terminal.app?
- Terminal.app and the Linux console quantize truecolor down to their 256- or 16-colour palette before rendering, so adjacent slightly-different RGB values collapse onto the same swatch. The fix is renderer-side: detect lack of truecolor via
$COLORTERM, and emit your gradient pre-quantized to 256 with bucket-aware steps instead. Seetruecolor-fallback-banding.
Terminal support
- xterm
- yes
- Linux console (fbcon)
- no
- macOS Terminal.app
- partial
- iTerm2
- yes
- Windows Terminal
- yes
- cmd.exe / ConPTY
- partial
- kitty
- yes
- alacritty
- yes
- WezTerm
- yes
- Ghostty
- yes
- GNOME Terminal
- yes
- Konsole
- yes
- tmux
- partial
- GNU screen
- partial
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| yes | no | partial | yes | yes | partial | yes | yes | yes | yes | yes | yes | partial | partial |