Skip to content
ASCII World

ASCII Control Characters

All 33 Non-Printing Codes and What They Do

By the ASCII World team

1. What Makes a Character a Control Character

A control character (also called a non-printing character) is an ASCII code point that does not map to a visible letter, digit, or symbol. Instead, it triggers an action: advance the paper, sound an alert, mark the end of a data block. The ASCII standard places them at positions 0-31 and 127, leaving positions 32-126 for printable characters.

Each control character has a two- or three-letter abbreviation (like NUL, LF, ESC) and a Unicode control picture for display purposes. These abbreviations come from the original teletype vocabulary: SOH meant "start of heading" on a telegraph circuit, not in a web page.

2. Origins: From Telegraph to Terminal

ASCII's control characters descend from 19th-century telegraph codes. The Baudot code (1870) had NUL and DEL. Donald Murray's 1901 revision added Carriage Return (CR) and Line Feed (LF) to control his teleprinter's print head. When the ASA committee designed ASCII in 1963, they included 33 control codes to cover everything from message framing to device synchronization.

By the late 1970s, most of these communication-oriented controls were obsolete. Protocols like TCP/IP handled message framing at the network layer, making SOH, STX, ETX, and EOT unnecessary for most applications. The formatting characters (CR, LF, TAB) survived because every text display still needs them. The ASCII timeline tracks how these transitions played out.

3. Groups by Function

The 33 control characters divide into six functional categories:

Communication Controls

Originally used to frame messages on serial links. SOH (1) marks header start, STX (2) marks body start, ETX (3) marks body end, and EOT (4) signals transmission complete. ACK (6) and NAK (21) provide positive/negative acknowledgment. DLE (16) escapes the next character for binary transparency.

Watch out: some legacy serial devices still expect these characters. Barcode scanners, POS terminals, and industrial PLCs sometimes use STX/ETX framing. If you strip control characters from serial data, you may break the protocol.

Formatting Characters

The survivors. LF (10) starts a new line. CR (13) returns to column zero. HT (9) advances to the next tab stop. BS (8) moves the cursor left one position. FF (12) ejects the current page on a printer. VT (11) advances vertically.

Line endings are a classic pain point: Unix uses LF, Windows uses CR+LF, and old Mac OS used CR alone. This mismatch causes visible ^M characters when transferring files between systems. Git handles this with core.autocrlf, but the problem still surprises people regularly. See the FAQ for common line ending questions.

Device Controls

DC1 (17) through DC4 (20) were intended for device-specific commands. DC1 and DC3 became XON/XOFF, the software flow control pair still used in serial terminals. When a receiver's buffer fills, it sends XOFF (DC3) to pause transmission; XON (DC1) resumes it. SO (14) and SI (15) switch between character sets on terminals that supported multiple fonts.

Information Separators

Four hierarchical delimiters for structuring data: FS (28, File Separator), GS (29, Group Separator), RS (30, Record Separator), and US (31, Unit Separator). These predate CSV and JSON by decades. Some barcode standards (GS1-128) still use GS as a field delimiter.

Error Controls

BEL (7) triggers an audible alert - the terminal bell that still works in most terminal emulators as \a. CAN (24) cancels the current operation. SUB (26) substitutes for an invalid character. On Windows, Ctrl+Z (which sends SUB) marks end-of-file in console input.

Special Characters

NUL (0) is the null character. C and C++ use it to terminate strings, so every "hello" literal actually occupies 6 bytes: 5 characters plus a NUL. ESC (27) starts escape sequences for terminal formatting (ANSI color codes begin with ESC + [). DEL (127) was designed to "erase" characters on paper tape by punching all seven holes.

4. Control Characters That Still Matter

Of the original 33, roughly 8 see daily use in modern systems:

  • NUL (0) - C string terminator, null byte in binary protocols
  • BEL (7) - terminal bell (\a in most languages)
  • BS (8) - backspace in terminal emulators
  • HT (9) - tab character in source code, TSV files, Makefiles
  • LF (10) - line ending on Unix, Linux, macOS
  • CR (13) - combined with LF for Windows line endings
  • ESC (27) - ANSI escape sequences for terminal colors and cursor control
  • DEL (127) - mapped to the Delete key on keyboards

The remaining 25 are effectively dead in general-purpose computing. They persist in niche protocols, legacy systems, and the occasional barcode standard. Use the text to ASCII converter to inspect control characters in any text, or browse all 33 on the control characters page.

5. Common Pitfalls

Stripping all control characters from input sounds safe but breaks legitimate data. Tab-separated files need HT. Multiline text needs LF. ANSI-colored terminal output needs ESC. Filter only the characters you know are dangerous for your context, not the entire 0-31 range.

NUL bytes inside strings cause truncation in C but are harmless in Python and JavaScript. If you process user input in a C-based system (like a CGI handler or database driver), always check for embedded NULs. They can bypass length checks and cause buffer interpretation errors.

References

  1. ASCII format for network interchangehttps://datatracker.ietf.org/doc/html/rfc20
  2. American National Standards Institute (ANSI). (1968). American Standard Code for Information Interchangehttps://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub1-2-1977.pdf
  3. Unicode Consortium. (2021). The Unicode Standard, Version 15.0.https://www.unicode.org/versions/components-15.0.0.html
  4. Yergeau, F. (1996). RFC 1345 - Character Mnemonics & Character Sets. Internet Engineering Task Force.https://datatracker.ietf.org/doc/rfc1345/
  5. Control Chareacter on Wikipediahttps://en.wikipedia.org/wiki/Control_character