Skip to main content
ansicode

DECRQDE / DECRPDE — Request / Report Displayed Extent (`CSI " v` / `" w`)

VT420+ pagination query — ask the terminal how many rows / columns are currently displayed and where the scroll window sits inside the page memory. Reply tells the host the visible viewport without relying on `tput lines / cols`.

Byte forms

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

\\x1b[\x1b["v DECRQDE (request)\n\x1b[<Ph>;<Pw>;<Pml>;<Pmt>;<Pmp>"w DECRPDE (reply)
\\033[\033["v / \033[<Ph>;<Pw>;<Pml>;<Pmt>;<Pmp>"w
\\e[\e["v / \e[<Ph>;<Pw>;<Pml>;<Pmt>;<Pmp>"w
ESC [ESC [ " v / ESC [ Ph ; Pw ; Pml ; Pmt ; Pmp " w
hex1b 5b 22 76 / 1b 5b … 22 77

Description

**DECRQDE** (*Request Displayed Extent*, `\x1b["v`) asks the terminal to describe the *visible viewport into its page memory*. The reply (**DECRPDE**, `\x1b[Ph;Pw;Pml;Pmt;Pmp"w`) carries five numbers: - **Ph** — number of rows visible in the viewport (almost always the terminal height). - **Pw** — number of columns visible (almost always the terminal width). - **Pml** — left margin column within the page (1-indexed; the leftmost column of the viewport relative to the page memory). - **Pmt** — top row of the viewport within the page memory (1-indexed; usually `1` unless the page is taller than the screen and scrolled). - **Pmp** — page number of the active page (1 on every single-page emulator; only meaningful on DEC VT525 with multi-page memory). **Why a separate query exists**: on classic DEC VT420/VT525 hardware, *page memory* could be larger than the screen — the terminal owned, say, 480 rows of buffer but only displayed 24 at a time, and the host needed to know what slice was on screen without redrawing. The query is the round-trip companion to **DECSCPP** (set columns-per-page) and **DECSLPP** (set lines-per-page) — host sets the geometry, terminal acknowledges via DECRPDE. **Modern usage**: in 2026, almost every emulator has a single page == single viewport == single screen-size buffer, so the reply is degenerate — `Ph` matches `LINES`, `Pw` matches `COLUMNS`, `Pml`/`Pmt`/`Pmp` are `1`. The *useful* role today is as a **feature probe**: terminals that reply at all are advertising VT420-class compatibility, which strongly correlates with support for DECRQTSR / DECRSTS, DECCARA, and the rectangle ops family. Programs that need to gate on 'real VT420 lineage' send `\x1b["v` and treat any reply as 'go'. **Reading the reply safely** - Emit `\x1b["v` to stdout. - Read from stdin with a 50–150 ms timeout. On no-reply terminals (most modern emulators), the timeout fires and you assume *no VT420 support*. - Parse `\x1b\[([0-9]+);([0-9]+);([0-9]+);([0-9]+);([0-9]+)"w` — anchored on the leading CSI and the final `"w` to avoid mis-framing on slow connections that interleave with user input. - **Critical**: terminals can prepend or append other reports if multiple queries are in flight — match the `"w` final byte, not position. **Coverage**: **xterm** = full (reference implementation). **mlterm** + **Konsole** + **gnome-terminal** = full. **WezTerm** = partial (replies, but `Pmt` always `1` regardless of actual scroll). **iTerm2** = no-op (silently consumed). **Kitty** + **Alacritty** + **Ghostty** + **Windows Terminal** + **cmd / ConPTY** + **macOS Terminal** + **Linux console** = no-op. The query is safe to emit unconditionally — non-replying terminals ignore the bytes; replying ones produce 5 small decimal fields parseable in < 30 bytes.

Spec citation: DEC VT420 / VT525 RM (DECRQDE / DECRPDE) / xterm-ctlseqs (CSI " v / " w)

Parameters

PhReply field: rows visible in the viewport.
PwReply field: columns visible in the viewport.
PmlReply field: leftmost column of the viewport within page memory (1-indexed).
PmtReply field: top row of the viewport within page memory (1-indexed).
PmpReply field: active page number (1 on single-page emulators).

Examples

bash
# Probe DECRQDE with a 100 ms read timeout.\nprintf '\\033["v'\nIFS= read -rs -d 'w' -t 0.1 reply </dev/tty 2>/dev/null\necho \"extent reply: ${reply}w\"   # e.g. \\x1b[24;80;1;1;1\"w
python
import sys, re, select\nsys.stdout.write('\\x1b["v')\nsys.stdout.flush()\nif select.select([sys.stdin], [], [], 0.1)[0]:\n    reply = sys.stdin.buffer.read1(64)\n    m = re.search(rb'\\x1b\\[(\\d+);(\\d+);(\\d+);(\\d+);(\\d+)\"w', reply)\n    if m:\n        h, w, ml, mt, mp = (int(x) for x in m.groups())\n        print(f'viewport: {h}x{w}, page-offset ({mt},{ml}), page {mp}')
go
// Feature-probe — treat any DECRPDE reply as 'VT420-class emulator'.\nimport (\n    \"fmt\"\n    \"os\"\n)\nfmt.Fprint(os.Stdout, \"\\x1b[\\\"v\")\n// Read with timeout (omitted); a non-empty reply => assume VT420 features.
javascript
// Trigger DECRQDE, log any reply.\nprocess.stdout.write('\\x1b[\"v');\nprocess.stdin.once('readable', () => {\n  const m = /\\x1b\\[(\\d+);(\\d+);(\\d+);(\\d+);(\\d+)\"w/.exec(process.stdin.read()?.toString('binary') ?? '');\n  if (m) console.error('extent:', m.slice(1));\n});
c
/* Send DECRQDE; the host expects DECRPDE within ~100 ms or gives up. */\nfputs(\"\\x1b[\\\"v\", stdout);\nfflush(stdout);\n/* Then poll stdin with select() and scanf the 5 decimal fields. */

Terminal support

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

Related sequences