Skip to main content
ansicode

OSC 8 — Inline hyperlink

Render clickable hyperlinks in terminal output (gnome-terminal 3.26+, iTerm2, Windows Terminal, kitty, ...).

Byte forms

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

\\x1b[\x1b]8;;URI\x07TEXT\x1b]8;;\x07
\\033[\033]8;;URI\007TEXT\033]8;;\007
\\e[\e]8;;URI\aTEXT\e]8;;\a
ESC [ESC ] 8 ; ; URI BEL TEXT ESC ] 8 ; ; BEL
hex1b 5d 38 3b 3b ... 07 ... 1b 5d 38 3b 3b 07

Live preview

Rendered in your browser via the same tokeniser the decoder uses — no terminal needed.

Description

OSC 8 — Inline Hyperlink. Specified in 2017 by gnome-terminal author Egmont Koblinger and adopted by iTerm2 3.5+, Windows Terminal 1.21+, kitty, wezterm, ghostty, Konsole 18.08+, libvte 0.50+ (so every gnome-terminal / xfce4-terminal / tilix that came after) and VS Code's integrated terminal. Two-part sequence: \x1b]8;params;URI BEL (or terminated by ST \x1b\\) opens a link region; \x1b]8;;BEL (empty URI) closes it. The middle TEXT can include any printable byte and further SGR — so you can wrap the link in \x1b[4;34m…\x1b[0m to get the familiar blue-underlined look (iTerm2 / ghostty / wezterm / recent gnome-terminal then render it as a true clickable link). Optional params: id=anchor is a hint that adjacent or non-adjacent runs sharing the same id belong to one logical link (used to span line-wrapped URLs without each cell becoming an independent hyperlink). URI scope: HTTP / HTTPS work on every emulator that supports OSC 8; file:// works in iTerm2 / wezterm / kitty / vscode-terminal; editor URIs (vscode://, cursor://, etc.) are partially supported.

Two failure modes bite the OSC 8 user. (1) Terminator hygiene: OSC sequences require an explicit terminator (BEL \x07 or ST \x1b\\); a missing terminator makes the parser keep eating bytes as link payload until one of them shows up — swallowing all of your subsequent program output until the next BEL / ST somewhere in the byte stream (see osc-terminator). Prefer BEL for xterm compatibility, ST for ECMA-48 strictness — pick one and use it consistently. (2) The id= semantic split: Kitty enforces id + url as the dedup key (same id + different url → two distinct links, which is what you want); pre-21.04 Konsole and pre-3.36 gnome-terminal use id-only dedup (same id + second url silently inherits the FIRST url — data corruption); iTerm2 ignores id entirely (every block is its own link); Windows Terminal accepts id but doesn't visually group across line wraps. Never re-use the same id= for two different URLs in one session — generate ids from a content hash or uuid (see osc8-id-rebind for the full compatibility table). Coverage: Linux console / fbcon and Alacritty (deliberate omission) render the entire OSC 8 envelope as nothing — your link text disappears, not just the underline. cmd.exe and Apple Terminal.app render the link text but with no clickability. Always provide a fallback that prints the URL inline (or the link text + ' (URL)') for users on these stacks.

There's no surgical 'close hyperlink' SGR — the canonical close is the empty-URI form \x1b]8;;\x07 (or \x1b]8;;\x1b\\). Combine with sgr-underline + sgr-fg-basic to style the visible text inside the hyperlink envelope without changing link semantics: \x1b]8;;https://example.com\x07\x1b[4;34mlink text\x1b[0m\x1b]8;;\x07. For window-title or working-directory updates that travel through the same OSC family and share the same terminator rules, see osc-title and osc-cwd. For clipboard interop via OSC 52, see osc-clipboard. Always pair OSC 8 emission with the audience check above — assume the conservative behaviour (text disappears on alacritty / Linux console) and ship a textual URL fallback in your CLI's --help or -l long-format mode for those users.

Spec citation: Hyperlinks in terminal emulators (gnome-terminal proposal, 2017)

Examples

bash
printf '\033]8;;https://example.com\033\\link text\033]8;;\033\\\n'
python
print('\x1b]8;;https://example.com\x07link text\x1b]8;;\x07')
go
fmt.Print("\x1b]8;;https://example.com\x07link text\x1b]8;;\x07\n")
javascript
console.log('\x1b]8;;https://example.com\x07link text\x1b]8;;\x07')
c
printf("\x1b]8;;https://example.com\x07link text\x1b]8;;\x07\n");

Used in

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

  • gh (GitHub CLI)issue / PR / diff output links to the github.com URL
  • git 2.40+file paths in some subcommands hyperlink with config `color.hyperlink`
  • ezafile names hyperlink to file:// URIs when run in a supporting terminal
  • pytest — traceback file paths
  • cargo build output — diagnostic URLs
  • deltagit pager — file path headers link to the file on disk

Frequently asked

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

Why does \x1b]8;;https://...\x1b\\ show up as raw text in my terminal?
Your terminal doesn't implement OSC 8, or you're inside a multiplexer that's swallowing the OSC. Modern terminals (iTerm2, kitty, ghostty, wezterm, alacritty, recent Windows Terminal / gnome-terminal) render it as a clickable link; older ones print the bytes verbatim. tmux specifically drops OSC 8 unless set -g allow-passthrough on — see the tmux-passthrough-dcs pitfall.
Can I use BEL (\a) instead of ST (\x1b\\) as the terminator?
Yes — both terminators are spec-valid and every OSC 8-aware terminal accepts both. BEL is the original xterm form and is byte-shorter; ST is the ECMA-48 canonical form. Pick one for your codebase and stay consistent — mixing them inside a single OSC payload is undefined.
Why do two adjacent OSC 8 links collapse into one giant link?
You forgot the closing \x1b]8;;\x1b\\ (empty URL) between them, or you reused the same id=… value across two different URLs and the terminal merged them. Always close every link before opening the next, and either omit id= or generate a fresh one per URL — see the osc8-id-rebind pitfall.

Terminal support

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

Related sequences

In the family cookbook

OSC cookbook · 3. OSC 8 hyperlinks — `\x1b]8;;URI\x07TEXT\x1b]8;;\x07`