How to Position the Cursor at Specific Coordinates on Screen in Batch Script
Creating an interactive, formatted CLI dashboard or a text-based game in Batch usually requires the ability to place text at a specific point on the screen rather than just printing everything line-by-line. In the past, this required third-party tools like nircmd. However, modern Windows terminals support ANSI Escape Sequences, allowing you to move the cursor precisely using native Batch commands.
In this guide, we will demonstrate how to position the cursor at specific X,Y coordinates using ANSI codes.
Understanding the Cursor Position Code
The ANSI escape code for cursor positioning is:
ESC[<Line>;<Column>H
- Line: The Y-coordinate (Row).
- Column: The X-coordinate (Column).
- H: The command to "Home" the cursor at those coordinates.
In terminal coordinates, 1;1 is the top-left corner of the window.
Method 1: The Native ANSI Approach (Recommended)
To use ANSI codes, we must first capture the Escape character into a variable.
The Positioning Script
@echo off
setlocal EnableExtensions EnableDelayedExpansion
chcp 65001 >nul
:: Correctly capture ESC character
for /f %%A in ('echo prompt $E ^| cmd') do set "ESC=%%A"
:: Validate ESC (debug-safe)
if not defined ESC (
echo ERROR: ESC not defined
pause
exit /b 1
)
cls
:: IMPORTANT: use delayed expansion carefully
<nul set /p "=!ESC![5;10HThis is at Row 5, Column 10"
<nul set /p "=!ESC![10;30HThis is at Row 10, Column 30"
<nul set /p "=!ESC![2;1HThis is at the top (Row 2)"
<nul set /p "=!ESC![12;1H------------------------------------------"
<nul set /p "=!ESC![14;1H[STATUS] Cursor positioning complete."
<nul set /p "=!ESC![15;1H------------------------------------------"
<nul set /p "=!ESC![17;1H"
pause >nul
endlocal
Method 2: Relative Positioning
Sometimes you don't know the exact absolute coordinates, but you want to move the cursor "up 2 lines" or "right 5 spaces" relative to its current position.
- Up:
ESC[<N>A - Down:
ESC[<N>B - Forward (Right):
ESC[<N>C - Back (Left):
ESC[<N>D
Example: Relocating the Cursor
@echo off
setlocal EnableExtensions EnableDelayedExpansion
chcp 65001 >nul
:: Get ESC character
for /f %%A in ('echo prompt $E ^| cmd') do set "ESC=%%A"
cls
echo Line 1
echo Line 2
echo Line 3
:: IMPORTANT: ensure we are on a known cursor state (start of next line)
<nul set /p "=!ESC![0J"
:: Move UP 2 lines to Line 2
<nul set /p "=!ESC![2A"
:: Clear entire line + return to column 1
<nul set /p "=!ESC![2K!ESC![G"
:: Overwrite Line 2 safely
<nul set /p "=This overwrites Line 2"
:: Go back to a known safe anchor (start of next line after overwrite)
echo.
:: Move DOWN 3 lines from current position
<nul set /p "=!ESC![3B"
:: Move RIGHT 20 columns and print text
<nul set /p "=!ESC![20CHere we moved 20 characters to the right."
:: Final safe position (avoid UI corruption)
<nul set /p "=!ESC![8;1H"
echo.
pause >nul
endlocal
Creating a "Status Bar" at the Top
A common use for cursor positioning is to have a header or status bar that stays at the top of the terminal while data scrolls underneath.
@echo off
setlocal EnableExtensions EnableDelayedExpansion
:: Generate ESC reliably
for /f %%A in ('echo prompt $E ^| cmd') do set "ESC=%%A"
cls
:: HEADER
<nul set /p "=!ESC![1;1H=========================================="
<nul set /p "=!ESC![2;1H SYSTEM MONITOR v1.0"
<nul set /p "=!ESC![3;1H=========================================="
:: LOG AREA
<nul set /p "=!ESC![5;1HLog entries starting here..."
:: IMPORTANT: force clean positioning (no echo mixing)
<nul set /p "=!ESC![6;1H"
<nul set /p "=Entry 1"
<nul set /p "=!ESC![7;1HEntry 2"
:: HEADER update
<nul set /p "=!ESC![2;30HCPU: 15%% "
:: LOG timestamp update
<nul set /p "=!ESC![5;30H(Updated at !TIME!) "
:: FINAL cursor position
<nul set /p "=!ESC![20;1H"
echo.
pause
endlocal
Performance and Compatibility
- Windows Version: These ANSI codes work natively in Windows 10 (version 1511 and later) and all versions of Windows 11. For older systems, the escape sequences will print as garbled text.
- Terminal choice: They work in the traditional
cmd.exe(ConHost) and look even smoother in the new Windows Terminal. - Speed: Moving the cursor via ANSI is significantly faster than using
clsand re-printing the whole screen, which causes noticeable "flicker."
Enabling ANSI in legacy ConHost: If colors and positioning do not work in cmd.exe, you may need to enable Virtual Terminal Processing via the registry:
reg add HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1 /f >nul 2>&1
A new console session is required after setting this value.
Summary Checklist
- Capture
ESC: Always use theprompt $Etrick to get a working Escape character variable. - Use delayed expansion: Define variables with
enabledelayedexpansionand reference them with!ESC!to avoid parsing issues with the non-printable escape character. - Use
<nul set /pfor positioning: When placing text at specific coordinates, use<nul set /p "=!ESC![Y;XH..."instead ofecho. Theechocommand appends a newline which advances the cursor after printing, defeating the purpose of precise placement. - Syntax: Use
!ESC![Y;XHto move. Remember: Row (Line) comes first, Column (X) comes second. - Cleanup: After you are done with your fancy layout, move the cursor to a safe place (below your UI) before the script ends, or the next command prompt will appear right on top of your work.
Conclusion
Cursor positioning transforms Batch from a simple "list of commands" into a platform for building functional, visually structured dashboards and interactive tools. By mastering the ESC[Line;ColumnH escape sequence, you gain complete control over the terminal real estate, allowing you to create professional command-line interfaces that are dynamic and intuitive.