ASCII: a working reference#

ASCII is the character encoding that almost everything else is built on top of. It defines 128 code points, numbered 0 to 127, and it has not changed since 1986. Learn it once and you have the bottom layer of text handling in every language, every protocol and every file format you will meet on a computer science course.

This page is the whole standard plus the parts that matter in practice: the tables, the bit tricks, the control characters nobody explains, the extended 8-bit code pages that came after, and how all of it relates to Unicode and UTF-8.

Reverse lookup

Type a character, a number in any base, a name, an abbreviation or a keystroke. Examples: A, 65, 0x41, 0101 (octal), 01000001, tab, ESC, ^C, &, pipe, curly.

A bare number means

Quick answers#

The four numbers worth memorising:

CharacterDecimalHexBinaryHandy because
048300011 0000c - '0' turns a digit character into its value
A65410100 0001Start of the uppercase run
a97610110 0001Start of the lowercase run, exactly 32 above A
space32200010 0000Lowest printable code, so it sorts before everything visible

Everything else can be derived. Z is A plus 25, so 90. z is 122. 9 is 57. The letters and digits are each one unbroken run, which is why range checks such as c >= 'a' && c <= 'z' are correct in ASCII (and why they are not correct in EBCDIC, where the alphabet has gaps).

The whole table in ten rows
RangeDecHexBinary patternContents
Control0-3100-1F000xxxxx / 0001xxxxNon-printing commands
Space32200010 0000The only printable whitespace
Punctuation33-4721-2F0010xxxx! " # $ % & ' ( ) * + , - . /
Digits48-5730-390011 xxxx0 to 9, low nibble is the value
Punctuation58-643A-400011/0100: ; < = > ? @
Uppercase65-9041-5A010xxxxxA to Z
Punctuation91-965B-600101/0110[ \ ] ^ _ `
Lowercase97-12261-7A011xxxxxa to z
Punctuation123-1267B-7E0111 11xx{ | } ~
Delete1277F0111 1111DEL, all seven bits set

The chart#

The classic layout. Read a code point by combining its column (the high 3 bits) with its row (the low 4 bits), so K sits in column 4, row B, which is 0x4B, decimal 75. Every structural property of ASCII is visible in this grid: the two control columns on the left, the two letter columns with uppercase directly above lowercase, and the digits stacked in column 3.

ASCII at a glance: column = high 3 bits, row = low 4 bits

How ASCII is laid out#

Seven bits, 128 code points#

ASCII is a 7-bit code. That is the single most important fact about it, and it explains the size of the table: 2 to the power 7 is 128, so the valid code points are 0 to 127 and nothing else.

Seven bits was a deliberate compromise. Six bits (64 characters) could not hold both cases of the alphabet plus digits and punctuation. Eight bits would have been wasteful on hardware where a character cost real money to store and transmit, and the eighth bit was wanted anyway: serial links used it as a parity bit for error detection.

The consequence you will hit in code is that a byte can hold values 128 to 255 that are not ASCII at all. "Extended ASCII" is not a standard, it is a family of mutually incompatible guesses about what those extra 128 values mean. See Beyond 7 bits.

The four columns of 32#

Split the table into four blocks of 32 and the design becomes obvious:

BlockRangeTop 2 bitsContents
00-3100Control characters
132-6301Space, punctuation, digits
264-9510@, uppercase A-Z, a few symbols
396-12711Backtick, lowercase a-z, a few symbols, DEL

Block 2 and block 3 are the same block with one bit changed. Block 0 is block 1 or block 2 with the top bits cleared. None of this is coincidence, and all of it is exploitable.

The case bit#

Bit 5, worth 32, is the only difference between an uppercase letter and its lowercase partner:

A = 0100 0001 = 65
a = 0110 0001 = 97
         ^
     bit 5, value 32

So for letters only:

c | 0x20    /* force lowercase */
c & ~0x20   /* force uppercase, that is c & 0xDF */
c ^ 0x20    /* swap the case */

The same 32 gap explains a subtler thing: because uppercase letters all have smaller code points than lowercase ones, a plain byte-order sort puts Zebra before apple. That is ASCIIbetical order, and it is not alphabetical order. Case-insensitive sorting is a deliberate extra step.

The digit trick#

Digits occupy 48 to 57, and their low four bits are the value of the digit:

'0' = 0011 0000 = 48    low nibble 0000 = 0
'7' = 0011 0111 = 55    low nibble 0111 = 7
'9' = 0011 1001 = 57    low nibble 1001 = 9

Which gives the two conversions you will write a hundred times:

int value  = c - '0';    /* character to number */
char digit = n + '0';    /* number to character */

That is the entire body of a simple atoi, and it is why c & 0x0F also works on a digit. Hexadecimal needs one extra step, because the letters are not adjacent to the digits:

int hexval(char c) {
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
    return -1;
}

The control key trick#

Control characters are not an arbitrary list bolted on to the front of the table. A control character is its printable partner with the top two bits cleared, which in hardware terms is what the Ctrl key on a terminal keyboard physically did:

C   = 0100 0011 = 67
^C  = 0000 0011 =  3   (ETX)

So Ctrl plus a key gives you key & 0x1F, or equivalently key - 64 for uppercase letters. Read the table the other way and every control character has an obvious keystroke:

This is also why terminal shortcuts cluster where they do. Ctrl+C, Ctrl+D, Ctrl+S and Ctrl+Z all have their behaviour because of what the corresponding control character meant.

Bit inspector

Click a bit to flip it and watch the character change. Bit 5 (value 32) is the case bit; bit 6 (value 64) separates letters from control characters and punctuation.

The full tables#

Four tables of 32 rows, matching the four blocks above. Every code point in ASCII appears exactly once across them.

Control characters: 0-31 and 127#

33 codes, with the keystroke that sends each one
DecHexOctBinaryAbbrNameCaretC escape
00000000000000NULNull^@\0
10100100000001SOHStart of Heading^Anone
20200200000010STXStart of Text^Bnone
30300300000011ETXEnd of Text^Cnone
40400400000100EOTEnd of Transmission^Dnone
50500500000101ENQEnquiry^Enone
60600600000110ACKAcknowledge^Fnone
70700700000111BELBell^G\a
80801000001000BSBackspace^H\b
90901100001001HTHorizontal Tab^I\t
100A01200001010LFLine Feed^J\n
110B01300001011VTVertical Tab^K\v
120C01400001100FFForm Feed^L\f
130D01500001101CRCarriage Return^M\r
140E01600001110SOShift Out^Nnone
150F01700001111SIShift In^Onone
161002000010000DLEData Link Escape^Pnone
171102100010001DC1Device Control 1^Qnone
181202200010010DC2Device Control 2^Rnone
191302300010011DC3Device Control 3^Snone
201402400010100DC4Device Control 4^Tnone
211502500010101NAKNegative Acknowledge^Unone
221602600010110SYNSynchronous Idle^Vnone
231702700010111ETBEnd of Transmission Block^Wnone
241803000011000CANCancel^Xnone
251903100011001EMEnd of Medium^Ynone
261A03200011010SUBSubstitute^Znone
271B03300011011ESCEscape^[\e
281C03400011100FSFile Separator^\none
291D03500011101GSGroup Separator^]none
301E03600011110RSRecord Separator^^none
311F03700011111USUnit Separator^_none
1277F17701111111DELDelete^?none

Codes 32-63: space, punctuation and digits#

The space, 15 punctuation marks, the ten digits and six more
DecHexOctBinaryCharNameHTMLType
322004000100000SPSpace&#32;Whitespace
332104100100001!Exclamation Mark&#33;Punctuation
342204200100010"Quotation Mark&quot;Punctuation
352304300100011#Number Sign&#35;Punctuation
362404400100100$Dollar Sign&#36;Punctuation
372504500100101%Percent Sign&#37;Punctuation
382604600100110&Ampersand&amp;Punctuation
392704700100111'Apostrophe&#39;Punctuation
402805000101000(Left Parenthesis&#40;Punctuation
412905100101001)Right Parenthesis&#41;Punctuation
422A05200101010*Asterisk&#42;Punctuation
432B05300101011+Plus Sign&#43;Punctuation
442C05400101100,Comma&#44;Punctuation
452D05500101101-Hyphen-Minus&#45;Punctuation
462E05600101110.Full Stop&#46;Punctuation
472F05700101111/Solidus&#47;Punctuation
4830060001100000Digit Zero&#48;Digit
4931061001100011Digit One&#49;Digit
5032062001100102Digit Two&#50;Digit
5133063001100113Digit Three&#51;Digit
5234064001101004Digit Four&#52;Digit
5335065001101015Digit Five&#53;Digit
5436066001101106Digit Six&#54;Digit
5537067001101117Digit Seven&#55;Digit
5638070001110008Digit Eight&#56;Digit
5739071001110019Digit Nine&#57;Digit
583A07200111010:Colon&#58;Punctuation
593B07300111011;Semicolon&#59;Punctuation
603C07400111100<Less-Than Sign&lt;Punctuation
613D07500111101=Equals Sign&#61;Punctuation
623E07600111110>Greater-Than Sign&gt;Punctuation
633F07700111111?Question Mark&#63;Punctuation

Codes 64-95: uppercase and symbols#

The at sign, A to Z, and five bracket-family symbols
DecHexOctBinaryCharNameHTMLType
644010001000000@Commercial At&#64;Punctuation
654110101000001ALatin Capital Letter A&#65;Uppercase letter
664210201000010BLatin Capital Letter B&#66;Uppercase letter
674310301000011CLatin Capital Letter C&#67;Uppercase letter
684410401000100DLatin Capital Letter D&#68;Uppercase letter
694510501000101ELatin Capital Letter E&#69;Uppercase letter
704610601000110FLatin Capital Letter F&#70;Uppercase letter
714710701000111GLatin Capital Letter G&#71;Uppercase letter
724811001001000HLatin Capital Letter H&#72;Uppercase letter
734911101001001ILatin Capital Letter I&#73;Uppercase letter
744A11201001010JLatin Capital Letter J&#74;Uppercase letter
754B11301001011KLatin Capital Letter K&#75;Uppercase letter
764C11401001100LLatin Capital Letter L&#76;Uppercase letter
774D11501001101MLatin Capital Letter M&#77;Uppercase letter
784E11601001110NLatin Capital Letter N&#78;Uppercase letter
794F11701001111OLatin Capital Letter O&#79;Uppercase letter
805012001010000PLatin Capital Letter P&#80;Uppercase letter
815112101010001QLatin Capital Letter Q&#81;Uppercase letter
825212201010010RLatin Capital Letter R&#82;Uppercase letter
835312301010011SLatin Capital Letter S&#83;Uppercase letter
845412401010100TLatin Capital Letter T&#84;Uppercase letter
855512501010101ULatin Capital Letter U&#85;Uppercase letter
865612601010110VLatin Capital Letter V&#86;Uppercase letter
875712701010111WLatin Capital Letter W&#87;Uppercase letter
885813001011000XLatin Capital Letter X&#88;Uppercase letter
895913101011001YLatin Capital Letter Y&#89;Uppercase letter
905A13201011010ZLatin Capital Letter Z&#90;Uppercase letter
915B13301011011[Left Square Bracket&#91;Punctuation
925C13401011100\Reverse Solidus&#92;Punctuation
935D13501011101]Right Square Bracket&#93;Punctuation
945E13601011110^Circumflex Accent&#94;Punctuation
955F13701011111_Low Line&#95;Punctuation

Codes 96-127: lowercase, symbols and DEL#

The backtick, a to z, four symbols and DEL
DecHexOctBinaryCharNameHTMLType
966014001100000`Grave Accent&#96;Punctuation
976114101100001aLatin Small Letter A&#97;Lowercase letter
986214201100010bLatin Small Letter B&#98;Lowercase letter
996314301100011cLatin Small Letter C&#99;Lowercase letter
1006414401100100dLatin Small Letter D&#100;Lowercase letter
1016514501100101eLatin Small Letter E&#101;Lowercase letter
1026614601100110fLatin Small Letter F&#102;Lowercase letter
1036714701100111gLatin Small Letter G&#103;Lowercase letter
1046815001101000hLatin Small Letter H&#104;Lowercase letter
1056915101101001iLatin Small Letter I&#105;Lowercase letter
1066A15201101010jLatin Small Letter J&#106;Lowercase letter
1076B15301101011kLatin Small Letter K&#107;Lowercase letter
1086C15401101100lLatin Small Letter L&#108;Lowercase letter
1096D15501101101mLatin Small Letter M&#109;Lowercase letter
1106E15601101110nLatin Small Letter N&#110;Lowercase letter
1116F15701101111oLatin Small Letter O&#111;Lowercase letter
1127016001110000pLatin Small Letter P&#112;Lowercase letter
1137116101110001qLatin Small Letter Q&#113;Lowercase letter
1147216201110010rLatin Small Letter R&#114;Lowercase letter
1157316301110011sLatin Small Letter S&#115;Lowercase letter
1167416401110100tLatin Small Letter T&#116;Lowercase letter
1177516501110101uLatin Small Letter U&#117;Lowercase letter
1187616601110110vLatin Small Letter V&#118;Lowercase letter
1197716701110111wLatin Small Letter W&#119;Lowercase letter
1207817001111000xLatin Small Letter X&#120;Lowercase letter
1217917101111001yLatin Small Letter Y&#121;Lowercase letter
1227A17201111010zLatin Small Letter Z&#122;Lowercase letter
1237B17301111011{Left Curly Bracket&#123;Punctuation
1247C17401111100|Vertical Line&#124;Punctuation
1257D17501111101}Right Curly Bracket&#125;Punctuation
1267E17601111110~Tilde&#126;Punctuation
1277F17701111111DELDelete&#127;Control

Control characters explained#

Thirty-three of the 128 code points print nothing. They were commands to a teleprinter or a communications link, and most are dead, but the survivors are load-bearing: you cannot write a network protocol, a terminal program or a file parser without meeting several of them.

What each one was designed to do, and where it survives
DecHexAbbrNameKeystrokeEscapeWhat it was for
000NULNullCtrl+@\0The all-zero byte. C uses it to mark the end of a string, which is why C strings cannot contain it. On paper tape it was blank tape, so it doubled as harmless padding.
101SOHStart of HeadingCtrl+A-Marked the start of a message header in old link protocols. Today it survives mostly as a field separator inside binary formats, and as the Ctrl+A keystroke (start of line in readline and tmux's prefix).
202STXStart of TextCtrl+B-Ended the header and began the message body. Still used as a frame marker in serial and point-of-sale protocols.
303ETXEnd of TextCtrl+C-Ended the message body. Far better known as Ctrl+C: terminals translate that keystroke into SIGINT, which is a terminal convention rather than anything ASCII mandates.
404EOTEnd of TransmissionCtrl+D-Ended the whole transmission. In a Unix terminal Ctrl+D sends no character at all: it tells the line discipline to flush the input buffer, which a reader sees as end of file.
505ENQEnquiryCtrl+E-Asked the far end to identify itself or confirm it was still alive. The ancestor of a keepalive ping.
606ACKAcknowledgeCtrl+F-Positive acknowledgement: the message arrived intact. Paired with NAK in stop-and-wait protocols such as XMODEM.
707BELBellCtrl+G\aRang the physical bell on a teletype. Terminals still beep or flash on it, and xterm-style title sequences are terminated by it.
808BSBackspaceCtrl+H\bMoved the print head back one position without erasing, so you could overstrike to make bold or accented characters. Note that the Backspace key usually sends DEL (127), not this.
909HTHorizontal TabCtrl+I\tAdvance to the next tab stop. The stop positions are a property of the display, not the data, which is the root of every tabs-versus-spaces alignment argument.
100ALFLine FeedCtrl+J\nMoved the paper up one line. Unix, Linux and macOS use it alone as the line terminator, and it is what C's \n means on those platforms.
110BVTVertical TabCtrl+K\vAdvance to the next vertical tab stop. Almost never used now, though it still counts as whitespace in most languages and as a line break in some Unicode algorithms.
120CFFForm FeedCtrl+L\fEjected the page on a printer. Some source files use it as a section separator, and Ctrl+L redraws the screen in many terminal programs.
130DCRCarriage ReturnCtrl+M\rReturned the print head to column one without advancing the line. Alone it is the classic-Mac line ending; followed by LF it is the Windows, HTTP, SMTP and CSV line ending.
140ESOShift OutCtrl+N-Switched to an alternate character set, an early escape hatch for going beyond 128 characters. Terminals still use it to select the line-drawing set.
150FSIShift InCtrl+O-Switched back to the standard character set after SO.
1610DLEData Link EscapeCtrl+P-Made the following characters mean something to the link layer rather than the application. The idea behind byte stuffing, which reappears in PPP and SLIP.
1711DC1Device Control 1Ctrl+Q-Device control, in practice XON: resume transmission. Ctrl+Q unfreezes a terminal frozen by Ctrl+S.
1812DC2Device Control 2Ctrl+R-Device control, historically used to turn an auxiliary device such as a tape punch on.
1913DC3Device Control 3Ctrl+S-Device control, in practice XOFF: pause transmission. This is why Ctrl+S appears to hang a terminal, and it is a common surprise when it collides with an editor's save shortcut.
2014DC4Device Control 4Ctrl+T-Device control, historically used to turn an auxiliary device off.
2115NAKNegative AcknowledgeCtrl+U-Negative acknowledgement: the message was damaged, send it again. The counterpart to ACK.
2216SYNSynchronous IdleCtrl+V-Filler sent on an idle synchronous line so that receiver and transmitter stayed in step. Ctrl+V is now widely repurposed as the literal-next-character key in terminals.
2317ETBEnd of Transmission BlockCtrl+W-Ended one block of a message that had been split for transmission, without ending the message itself.
2418CANCancelCtrl+X-Told the receiver to discard the data that came before it. XMODEM still uses it to abort a transfer.
2519EMEnd of MediumCtrl+Y-Marked the physical end of the tape, card or other medium, which is not necessarily the end of the data.
261ASUBSubstituteCtrl+Z-Stood in for a character that could not be represented. DOS adopted it as the end-of-file marker in text files, and Unix shells use Ctrl+Z to suspend a job.
271BESCEscapeCtrl+[\eIntroduces an escape sequence, giving the following characters a special meaning. Every ANSI terminal colour, cursor move and key code starts here. Note \e is a GNU extension, not standard C.
281CFSFile SeparatorCtrl+\-The coarsest of the four data separators: divides files within a stream.
291DGSGroup SeparatorCtrl+]-Divides groups of records. Used in GS1 barcode data and in some EDI formats.
301ERSRecord SeparatorCtrl+^-Divides records. ASCII-delimited text uses it as the row terminator instead of a newline, so records can contain newlines safely.
311FUSUnit SeparatorCtrl+_-The finest separator: divides fields within a record. RS and US together give you a CSV that never needs quoting or escaping.
1277FDELDeleteCtrl+?-All seven bits set. On paper tape you deleted a character by punching every hole, so the reader skipped it. It sits at the end of the table rather than with the other controls for exactly that reason, and it is what most Backspace keys actually send.

Line endings, the one that actually bites#

CR (13) and LF (10) are two separate characters because a teleprinter needed two separate motions: return the carriage to the left margin, and advance the paper by one line. Operating systems then disagreed about which to keep.

ConventionBytesWrittenUsed by
LF0A\nUnix, Linux, macOS since OS X, most programming languages
CRLF0D 0A\r\nWindows, HTTP, SMTP, FTP, CSV per RFC 4180, most internet protocols
CR0D\rClassic Mac OS up to version 9, now effectively extinct

Practical consequences:

The four separators nobody uses#

Codes 28 to 31 are FS, GS, RS and US: a four-level hierarchy of delimiters, built into ASCII from the start, and almost entirely ignored.

US (31)  separates fields   inside a record
RS (30)  separates records  inside a group
GS (29)  separates groups   inside a file
FS (28)  separates files    inside a stream

The point is that these characters never appear in ordinary text, so a format built on them needs no quoting, no escaping and no rules about commas inside values. Every CSV parsing bug in history exists because the world picked a comma, which appears in real data, over US, which does not. They are still used in GS1 barcodes and some EDI and point-of-sale formats, and they are a reasonable choice for a quick internal data dump.

Characters that are whitespace#

Six ASCII code points count as whitespace for isspace in C and for \s in most regular expression flavours:

CodeCharNameIn \sIn isspace
9\tHorizontal tabyesyes
10\nLine feedyesyes
11\vVertical tabyesyes
12\fForm feedyesyes
13\rCarriage returnyesyes
32spaceSpaceyesyes

Note what is not in that list: NUL is not whitespace, and neither is the no-break space at 160, which is not ASCII at all but turns up constantly in text copied from web pages and word processors. It looks exactly like a space and fails every equality test against one.

Printable characters worth knowing#

Printable characters worth knowing the number of
DecCharNameWhy it matters
32SPSpaceCode point 32 is the only printable character that is also whitespace. Its position immediately before the punctuation block means it sorts before every visible character.
34"Quotation MarkMust be escaped inside a double-quoted string in most languages, and inside JSON always.
38&AmpersandMust be escaped as &amp;amp; in HTML and XML, including inside URLs written in HTML.
39'ApostropheDifferent from the typographic apostrophe U+2019, which is what a word processor inserts. That mismatch is a common source of broken code pasted from a document.
45-Hyphen-MinusAlso called hyphen-minus because ASCII has one character doing both jobs. Unicode separates them.
47/SolidusThe path separator everywhere except Windows, and the only character besides NUL that a Unix filename may not contain.
480Digit ZeroThe digits 48 to 57 are contiguous and their low four bits are the digit's value, so c - '0' converts a digit character to its number.
60<Less-Than SignMust be escaped as &amp;lt; in HTML. Unescaped user input containing it is the classic XSS vector.
64@Commercial AtChosen for email addresses by Ray Tomlinson in 1971 because it could not appear in a user name.
65ALatin Capital Letter AA is 65 and a is 97. The gap is exactly 32, one bit, which is the whole trick behind ASCII case conversion.
92\Reverse SolidusThe escape character in almost every string literal, which is why Windows paths need doubling in source code.
94^Circumflex AccentWritten as ^ in caret notation for control characters, so Ctrl+C is written ^C.
96`Grave AccentStarts a template literal in JavaScript, a code span in Markdown and command substitution in older shell scripts.
97aLatin Small Letter ALowercase letters run 97 to 122. Because they come after the uppercase letters, a naive byte sort puts Zebra before apple.

Converting between representations#

Text and codes converter

Type text on the left to see its codes, or paste codes on the right to decode them. The decoder accepts decimal, 0x41, 41h, \x41, \101, U+0041, &#65; and bare binary, separated by spaces, commas or newlines.

Doing it by hand#

Hex is the natural way to write ASCII because one hex digit is exactly four bits, so a byte is always two digits and the split lines up with the structure of the table. Octal is a leftover from machines with 12, 18 and 36 bit words, and it survives in C escapes and in Unix file permissions.

binary   0100 0001
hex         4    1     = 0x41
decimal  64 + 1        = 65
octal    001 000 001   = 0101   (group in threes from the right)

To go from decimal to binary quickly, subtract the powers of two from the left:

75 - 64 = 11   so bit 6 is set   (0100 0000)
11 - 8  = 3    so bit 3 is set   (0000 1000)
3  - 2  = 1    so bit 1 is set   (0000 0010)
1  - 1  = 0    so bit 0 is set   (0000 0001)
                          total   0100 1011 = 'K'

Doing it in code#

TaskCPythonJavaJavaScript
Character to code(int) cord(c)(int) cs.charCodeAt(0)
Code to character(char) nchr(n)(char) nString.fromCharCode(n)
To hexprintf("%02X", c)format(n, "02X")String.format("%02X", n)n.toString(16)
To binarymanual shift loopformat(n, "08b")Integer.toBinaryString(n)n.toString(2)
Parse hexstrtol(s, 0, 16)int(s, 16)Integer.parseInt(s, 16)parseInt(s, 16)
Whole string to bytes(unsigned char *) ss.encode("ascii")s.getBytes(US_ASCII)new TextEncoder().encode(s)
Is it ASCIIc >= 0 && c < 128s.isascii()c < 128/^[\x00-\x7F]*$/.test(s)

Useful command line one-liners:

# Show the bytes of a file, with printable characters alongside
xxd file.txt | head

# Same idea, named characters, good for spotting stray control bytes
od -c file.txt | head

# Look up a single character
python3 -c "print(ord('A'))"

# Print the whole printable range
python3 -c "print(''.join(chr(i) for i in range(32,127)))"

# The manual page that ships with most Unix systems
man 7 ascii

# Find non-ASCII bytes in a file
grep -nP '[^\x00-\x7F]' file.txt

Beyond 7 bits: the extended code pages#

Once bytes were reliably 8 bits, the parity bit became free real estate, and everyone filled codes 128 to 255 differently. There is no such thing as "extended ASCII" as a single standard. If a file contains a byte above 127, you cannot know what character it means without being told the encoding.

The three sets below are the ones you are most likely to meet. All three agree exactly with ASCII for bytes 0 to 127, which is the only reason mixed-encoding text is ever partially readable.

ISO 8859-1, also called Latin-1#

The ISO standard for Western European languages, and for a long time the default assumption for HTTP and for many databases. Bytes 160 to 255 are accented letters and common symbols. Bytes 128 to 159 are the C1 control range and are not printable characters at all.

Latin-1 has one property that makes it special: its 256 characters map one to one onto the first 256 Unicode code points. Decoding arbitrary bytes as Latin-1 therefore never fails, which makes it a useful last resort for reading a file of unknown encoding without an exception, and a dangerous default because it silently produces nonsense rather than an error.

ISO 8859-1 (Latin-1), bytes 128-255
DecHexBinaryCharUnicodeNameUTF-8 bytes
1288010000000--U+0080PAD (C1 control)C2 80
1298110000001--U+0081HOP (C1 control)C2 81
1308210000010--U+0082BPH (C1 control)C2 82
1318310000011--U+0083NBH (C1 control)C2 83
1328410000100--U+0084IND (C1 control)C2 84
1338510000101--U+0085NEL (C1 control)C2 85
1348610000110--U+0086SSA (C1 control)C2 86
1358710000111--U+0087ESA (C1 control)C2 87
1368810001000--U+0088HTS (C1 control)C2 88
1378910001001--U+0089HTJ (C1 control)C2 89
1388A10001010--U+008AVTS (C1 control)C2 8A
1398B10001011--U+008BPLD (C1 control)C2 8B
1408C10001100--U+008CPLU (C1 control)C2 8C
1418D10001101--U+008DRI (C1 control)C2 8D
1428E10001110--U+008ESS2 (C1 control)C2 8E
1438F10001111--U+008FSS3 (C1 control)C2 8F
1449010010000--U+0090DCS (C1 control)C2 90
1459110010001--U+0091PU1 (C1 control)C2 91
1469210010010--U+0092PU2 (C1 control)C2 92
1479310010011--U+0093STS (C1 control)C2 93
1489410010100--U+0094CCH (C1 control)C2 94
1499510010101--U+0095MW (C1 control)C2 95
1509610010110--U+0096SPA (C1 control)C2 96
1519710010111--U+0097EPA (C1 control)C2 97
1529810011000--U+0098SOS (C1 control)C2 98
1539910011001--U+0099SGC (C1 control)C2 99
1549A10011010--U+009ASCI (C1 control)C2 9A
1559B10011011--U+009BCSI (C1 control)C2 9B
1569C10011100--U+009CST (C1 control)C2 9C
1579D10011101--U+009DOSC (C1 control)C2 9D
1589E10011110--U+009EPM (C1 control)C2 9E
1599F10011111--U+009FAPC (C1 control)C2 9F
160A010100000 U+00A0No-Break SpaceC2 A0
161A110100001¡U+00A1Inverted Exclamation MarkC2 A1
162A210100010¢U+00A2Cent SignC2 A2
163A310100011£U+00A3Pound SignC2 A3
164A410100100¤U+00A4Currency SignC2 A4
165A510100101¥U+00A5Yen SignC2 A5
166A610100110¦U+00A6Broken BarC2 A6
167A710100111§U+00A7Section SignC2 A7
168A810101000¨U+00A8DiaeresisC2 A8
169A910101001©U+00A9Copyright SignC2 A9
170AA10101010ªU+00AAFeminine Ordinal IndicatorC2 AA
171AB10101011«U+00ABLeft-Pointing Double Angle Quotation MarkC2 AB
172AC10101100¬U+00ACNot SignC2 AC
173AD10101101­U+00ADSoft HyphenC2 AD
174AE10101110®U+00AERegistered SignC2 AE
175AF10101111¯U+00AFMacronC2 AF
176B010110000°U+00B0Degree SignC2 B0
177B110110001±U+00B1Plus-Minus SignC2 B1
178B210110010²U+00B2Superscript TwoC2 B2
179B310110011³U+00B3Superscript ThreeC2 B3
180B410110100´U+00B4Acute AccentC2 B4
181B510110101µU+00B5Micro SignC2 B5
182B610110110U+00B6Pilcrow SignC2 B6
183B710110111·U+00B7Middle DotC2 B7
184B810111000¸U+00B8CedillaC2 B8
185B910111001¹U+00B9Superscript OneC2 B9
186BA10111010ºU+00BAMasculine Ordinal IndicatorC2 BA
187BB10111011»U+00BBRight-Pointing Double Angle Quotation MarkC2 BB
188BC10111100¼U+00BCVulgar Fraction One QuarterC2 BC
189BD10111101½U+00BDVulgar Fraction One HalfC2 BD
190BE10111110¾U+00BEVulgar Fraction Three QuartersC2 BE
191BF10111111¿U+00BFInverted Question MarkC2 BF
192C011000000ÀU+00C0Latin Capital Letter A With GraveC3 80
193C111000001ÁU+00C1Latin Capital Letter A With AcuteC3 81
194C211000010ÂU+00C2Latin Capital Letter A With CircumflexC3 82
195C311000011ÃU+00C3Latin Capital Letter A With TildeC3 83
196C411000100ÄU+00C4Latin Capital Letter A With DiaeresisC3 84
197C511000101ÅU+00C5Latin Capital Letter A With Ring AboveC3 85
198C611000110ÆU+00C6Latin Capital Letter AEC3 86
199C711000111ÇU+00C7Latin Capital Letter C With CedillaC3 87
200C811001000ÈU+00C8Latin Capital Letter E With GraveC3 88
201C911001001ÉU+00C9Latin Capital Letter E With AcuteC3 89
202CA11001010ÊU+00CALatin Capital Letter E With CircumflexC3 8A
203CB11001011ËU+00CBLatin Capital Letter E With DiaeresisC3 8B
204CC11001100ÌU+00CCLatin Capital Letter I With GraveC3 8C
205CD11001101ÍU+00CDLatin Capital Letter I With AcuteC3 8D
206CE11001110ÎU+00CELatin Capital Letter I With CircumflexC3 8E
207CF11001111ÏU+00CFLatin Capital Letter I With DiaeresisC3 8F
208D011010000ÐU+00D0Latin Capital Letter EthC3 90
209D111010001ÑU+00D1Latin Capital Letter N With TildeC3 91
210D211010010ÒU+00D2Latin Capital Letter O With GraveC3 92
211D311010011ÓU+00D3Latin Capital Letter O With AcuteC3 93
212D411010100ÔU+00D4Latin Capital Letter O With CircumflexC3 94
213D511010101ÕU+00D5Latin Capital Letter O With TildeC3 95
214D611010110ÖU+00D6Latin Capital Letter O With DiaeresisC3 96
215D711010111×U+00D7Multiplication SignC3 97
216D811011000ØU+00D8Latin Capital Letter O With StrokeC3 98
217D911011001ÙU+00D9Latin Capital Letter U With GraveC3 99
218DA11011010ÚU+00DALatin Capital Letter U With AcuteC3 9A
219DB11011011ÛU+00DBLatin Capital Letter U With CircumflexC3 9B
220DC11011100ÜU+00DCLatin Capital Letter U With DiaeresisC3 9C
221DD11011101ÝU+00DDLatin Capital Letter Y With AcuteC3 9D
222DE11011110ÞU+00DELatin Capital Letter ThornC3 9E
223DF11011111ßU+00DFLatin Small Letter Sharp SC3 9F
224E011100000àU+00E0Latin Small Letter A With GraveC3 A0
225E111100001áU+00E1Latin Small Letter A With AcuteC3 A1
226E211100010âU+00E2Latin Small Letter A With CircumflexC3 A2
227E311100011ãU+00E3Latin Small Letter A With TildeC3 A3
228E411100100äU+00E4Latin Small Letter A With DiaeresisC3 A4
229E511100101åU+00E5Latin Small Letter A With Ring AboveC3 A5
230E611100110æU+00E6Latin Small Letter AEC3 A6
231E711100111çU+00E7Latin Small Letter C With CedillaC3 A7
232E811101000èU+00E8Latin Small Letter E With GraveC3 A8
233E911101001éU+00E9Latin Small Letter E With AcuteC3 A9
234EA11101010êU+00EALatin Small Letter E With CircumflexC3 AA
235EB11101011ëU+00EBLatin Small Letter E With DiaeresisC3 AB
236EC11101100ìU+00ECLatin Small Letter I With GraveC3 AC
237ED11101101íU+00EDLatin Small Letter I With AcuteC3 AD
238EE11101110îU+00EELatin Small Letter I With CircumflexC3 AE
239EF11101111ïU+00EFLatin Small Letter I With DiaeresisC3 AF
240F011110000ðU+00F0Latin Small Letter EthC3 B0
241F111110001ñU+00F1Latin Small Letter N With TildeC3 B1
242F211110010òU+00F2Latin Small Letter O With GraveC3 B2
243F311110011óU+00F3Latin Small Letter O With AcuteC3 B3
244F411110100ôU+00F4Latin Small Letter O With CircumflexC3 B4
245F511110101õU+00F5Latin Small Letter O With TildeC3 B5
246F611110110öU+00F6Latin Small Letter O With DiaeresisC3 B6
247F711110111÷U+00F7Division SignC3 B7
248F811111000øU+00F8Latin Small Letter O With StrokeC3 B8
249F911111001ùU+00F9Latin Small Letter U With GraveC3 B9
250FA11111010úU+00FALatin Small Letter U With AcuteC3 BA
251FB11111011ûU+00FBLatin Small Letter U With CircumflexC3 BB
252FC11111100üU+00FCLatin Small Letter U With DiaeresisC3 BC
253FD11111101ýU+00FDLatin Small Letter Y With AcuteC3 BD
254FE11111110þU+00FELatin Small Letter ThornC3 BE
255FF11111111ÿU+00FFLatin Small Letter Y With DiaeresisC3 BF

Windows-1252#

Microsoft's near-identical variant, and the real encoding behind a great deal of text that claims to be Latin-1. It matches ISO 8859-1 everywhere except 128 to 159, where instead of C1 controls it puts typographic characters: curly quotes, the en dash and em dash, the bullet, the ellipsis and the euro sign.

This single difference causes most of the mojibake on the web. A document is labelled ISO-8859-1, actually contains Windows-1252, and its curly quotes decode as invisible control characters or as replacement characters. The HTML5 specification gave up and requires browsers to decode anything labelled ISO-8859-1 as windows-1252 instead.

Windows-1252, bytes 128-255
DecHexBinaryCharUnicodeNameUTF-8 bytes
1288010000000U+20ACEuro SignE2 82 AC
1298110000001---Undefined-
1308210000010U+201ASingle Low-9 Quotation MarkE2 80 9A
1318310000011ƒU+0192Latin Small Letter F With HookC6 92
1328410000100U+201EDouble Low-9 Quotation MarkE2 80 9E
1338510000101U+2026Horizontal EllipsisE2 80 A6
1348610000110U+2020DaggerE2 80 A0
1358710000111U+2021Double DaggerE2 80 A1
1368810001000ˆU+02C6Modifier Letter Circumflex AccentCB 86
1378910001001U+2030Per Mille SignE2 80 B0
1388A10001010ŠU+0160Latin Capital Letter S With CaronC5 A0
1398B10001011U+2039Single Left-Pointing Angle Quotation MarkE2 80 B9
1408C10001100ŒU+0152Latin Capital Ligature OEC5 92
1418D10001101---Undefined-
1428E10001110ŽU+017DLatin Capital Letter Z With CaronC5 BD
1438F10001111---Undefined-
1449010010000---Undefined-
1459110010001U+2018Left Single Quotation MarkE2 80 98
1469210010010U+2019Right Single Quotation MarkE2 80 99
1479310010011U+201CLeft Double Quotation MarkE2 80 9C
1489410010100U+201DRight Double Quotation MarkE2 80 9D
1499510010101U+2022BulletE2 80 A2
1509610010110U+2013En DashE2 80 93
1519710010111U+2014Em DashE2 80 94
1529810011000˜U+02DCSmall TildeCB 9C
1539910011001U+2122Trade Mark SignE2 84 A2
1549A10011010šU+0161Latin Small Letter S With CaronC5 A1
1559B10011011U+203ASingle Right-Pointing Angle Quotation MarkE2 80 BA
1569C10011100œU+0153Latin Small Ligature OEC5 93
1579D10011101---Undefined-
1589E10011110žU+017ELatin Small Letter Z With CaronC5 BE
1599F10011111ŸU+0178Latin Capital Letter Y With DiaeresisC5 B8
160A010100000 U+00A0No-Break SpaceC2 A0
161A110100001¡U+00A1Inverted Exclamation MarkC2 A1
162A210100010¢U+00A2Cent SignC2 A2
163A310100011£U+00A3Pound SignC2 A3
164A410100100¤U+00A4Currency SignC2 A4
165A510100101¥U+00A5Yen SignC2 A5
166A610100110¦U+00A6Broken BarC2 A6
167A710100111§U+00A7Section SignC2 A7
168A810101000¨U+00A8DiaeresisC2 A8
169A910101001©U+00A9Copyright SignC2 A9
170AA10101010ªU+00AAFeminine Ordinal IndicatorC2 AA
171AB10101011«U+00ABLeft-Pointing Double Angle Quotation MarkC2 AB
172AC10101100¬U+00ACNot SignC2 AC
173AD10101101­U+00ADSoft HyphenC2 AD
174AE10101110®U+00AERegistered SignC2 AE
175AF10101111¯U+00AFMacronC2 AF
176B010110000°U+00B0Degree SignC2 B0
177B110110001±U+00B1Plus-Minus SignC2 B1
178B210110010²U+00B2Superscript TwoC2 B2
179B310110011³U+00B3Superscript ThreeC2 B3
180B410110100´U+00B4Acute AccentC2 B4
181B510110101µU+00B5Micro SignC2 B5
182B610110110U+00B6Pilcrow SignC2 B6
183B710110111·U+00B7Middle DotC2 B7
184B810111000¸U+00B8CedillaC2 B8
185B910111001¹U+00B9Superscript OneC2 B9
186BA10111010ºU+00BAMasculine Ordinal IndicatorC2 BA
187BB10111011»U+00BBRight-Pointing Double Angle Quotation MarkC2 BB
188BC10111100¼U+00BCVulgar Fraction One QuarterC2 BC
189BD10111101½U+00BDVulgar Fraction One HalfC2 BD
190BE10111110¾U+00BEVulgar Fraction Three QuartersC2 BE
191BF10111111¿U+00BFInverted Question MarkC2 BF
192C011000000ÀU+00C0Latin Capital Letter A With GraveC3 80
193C111000001ÁU+00C1Latin Capital Letter A With AcuteC3 81
194C211000010ÂU+00C2Latin Capital Letter A With CircumflexC3 82
195C311000011ÃU+00C3Latin Capital Letter A With TildeC3 83
196C411000100ÄU+00C4Latin Capital Letter A With DiaeresisC3 84
197C511000101ÅU+00C5Latin Capital Letter A With Ring AboveC3 85
198C611000110ÆU+00C6Latin Capital Letter AEC3 86
199C711000111ÇU+00C7Latin Capital Letter C With CedillaC3 87
200C811001000ÈU+00C8Latin Capital Letter E With GraveC3 88
201C911001001ÉU+00C9Latin Capital Letter E With AcuteC3 89
202CA11001010ÊU+00CALatin Capital Letter E With CircumflexC3 8A
203CB11001011ËU+00CBLatin Capital Letter E With DiaeresisC3 8B
204CC11001100ÌU+00CCLatin Capital Letter I With GraveC3 8C
205CD11001101ÍU+00CDLatin Capital Letter I With AcuteC3 8D
206CE11001110ÎU+00CELatin Capital Letter I With CircumflexC3 8E
207CF11001111ÏU+00CFLatin Capital Letter I With DiaeresisC3 8F
208D011010000ÐU+00D0Latin Capital Letter EthC3 90
209D111010001ÑU+00D1Latin Capital Letter N With TildeC3 91
210D211010010ÒU+00D2Latin Capital Letter O With GraveC3 92
211D311010011ÓU+00D3Latin Capital Letter O With AcuteC3 93
212D411010100ÔU+00D4Latin Capital Letter O With CircumflexC3 94
213D511010101ÕU+00D5Latin Capital Letter O With TildeC3 95
214D611010110ÖU+00D6Latin Capital Letter O With DiaeresisC3 96
215D711010111×U+00D7Multiplication SignC3 97
216D811011000ØU+00D8Latin Capital Letter O With StrokeC3 98
217D911011001ÙU+00D9Latin Capital Letter U With GraveC3 99
218DA11011010ÚU+00DALatin Capital Letter U With AcuteC3 9A
219DB11011011ÛU+00DBLatin Capital Letter U With CircumflexC3 9B
220DC11011100ÜU+00DCLatin Capital Letter U With DiaeresisC3 9C
221DD11011101ÝU+00DDLatin Capital Letter Y With AcuteC3 9D
222DE11011110ÞU+00DELatin Capital Letter ThornC3 9E
223DF11011111ßU+00DFLatin Small Letter Sharp SC3 9F
224E011100000àU+00E0Latin Small Letter A With GraveC3 A0
225E111100001áU+00E1Latin Small Letter A With AcuteC3 A1
226E211100010âU+00E2Latin Small Letter A With CircumflexC3 A2
227E311100011ãU+00E3Latin Small Letter A With TildeC3 A3
228E411100100äU+00E4Latin Small Letter A With DiaeresisC3 A4
229E511100101åU+00E5Latin Small Letter A With Ring AboveC3 A5
230E611100110æU+00E6Latin Small Letter AEC3 A6
231E711100111çU+00E7Latin Small Letter C With CedillaC3 A7
232E811101000èU+00E8Latin Small Letter E With GraveC3 A8
233E911101001éU+00E9Latin Small Letter E With AcuteC3 A9
234EA11101010êU+00EALatin Small Letter E With CircumflexC3 AA
235EB11101011ëU+00EBLatin Small Letter E With DiaeresisC3 AB
236EC11101100ìU+00ECLatin Small Letter I With GraveC3 AC
237ED11101101íU+00EDLatin Small Letter I With AcuteC3 AD
238EE11101110îU+00EELatin Small Letter I With CircumflexC3 AE
239EF11101111ïU+00EFLatin Small Letter I With DiaeresisC3 AF
240F011110000ðU+00F0Latin Small Letter EthC3 B0
241F111110001ñU+00F1Latin Small Letter N With TildeC3 B1
242F211110010òU+00F2Latin Small Letter O With GraveC3 B2
243F311110011óU+00F3Latin Small Letter O With AcuteC3 B3
244F411110100ôU+00F4Latin Small Letter O With CircumflexC3 B4
245F511110101õU+00F5Latin Small Letter O With TildeC3 B5
246F611110110öU+00F6Latin Small Letter O With DiaeresisC3 B6
247F711110111÷U+00F7Division SignC3 B7
248F811111000øU+00F8Latin Small Letter O With StrokeC3 B8
249F911111001ùU+00F9Latin Small Letter U With GraveC3 B9
250FA11111010úU+00FALatin Small Letter U With AcuteC3 BA
251FB11111011ûU+00FBLatin Small Letter U With CircumflexC3 BB
252FC11111100üU+00FCLatin Small Letter U With DiaeresisC3 BC
253FD11111101ýU+00FDLatin Small Letter Y With AcuteC3 BD
254FE11111110þU+00FELatin Small Letter ThornC3 BE
255FF11111111ÿU+00FFLatin Small Letter Y With DiaeresisC3 BF

Code page 437#

The character set burned into the ROM of the original IBM PC. It uses the upper 128 for accented letters, Greek letters, mathematical symbols and, most famously, the box-drawing and shading characters that every DOS-era text interface was built from. Anyone who has seen an old installer's blue screen with double-line borders has seen CP437.

It is worth knowing for two reasons: it is the encoding of a great deal of historical material, including ANSI art and the text-mode games of the period, and its box-drawing characters were all adopted into Unicode, so you can still use them today.

Code page 437, the original IBM PC set, bytes 128-255
DecHexBinaryCharUnicodeNameUTF-8 bytes
1288010000000ÇU+00C7Latin Capital Letter C With CedillaC3 87
1298110000001üU+00FCLatin Small Letter U With DiaeresisC3 BC
1308210000010éU+00E9Latin Small Letter E With AcuteC3 A9
1318310000011âU+00E2Latin Small Letter A With CircumflexC3 A2
1328410000100äU+00E4Latin Small Letter A With DiaeresisC3 A4
1338510000101àU+00E0Latin Small Letter A With GraveC3 A0
1348610000110åU+00E5Latin Small Letter A With Ring AboveC3 A5
1358710000111çU+00E7Latin Small Letter C With CedillaC3 A7
1368810001000êU+00EALatin Small Letter E With CircumflexC3 AA
1378910001001ëU+00EBLatin Small Letter E With DiaeresisC3 AB
1388A10001010èU+00E8Latin Small Letter E With GraveC3 A8
1398B10001011ïU+00EFLatin Small Letter I With DiaeresisC3 AF
1408C10001100îU+00EELatin Small Letter I With CircumflexC3 AE
1418D10001101ìU+00ECLatin Small Letter I With GraveC3 AC
1428E10001110ÄU+00C4Latin Capital Letter A With DiaeresisC3 84
1438F10001111ÅU+00C5Latin Capital Letter A With Ring AboveC3 85
1449010010000ÉU+00C9Latin Capital Letter E With AcuteC3 89
1459110010001æU+00E6Latin Small Letter AEC3 A6
1469210010010ÆU+00C6Latin Capital Letter AEC3 86
1479310010011ôU+00F4Latin Small Letter O With CircumflexC3 B4
1489410010100öU+00F6Latin Small Letter O With DiaeresisC3 B6
1499510010101òU+00F2Latin Small Letter O With GraveC3 B2
1509610010110ûU+00FBLatin Small Letter U With CircumflexC3 BB
1519710010111ùU+00F9Latin Small Letter U With GraveC3 B9
1529810011000ÿU+00FFLatin Small Letter Y With DiaeresisC3 BF
1539910011001ÖU+00D6Latin Capital Letter O With DiaeresisC3 96
1549A10011010ÜU+00DCLatin Capital Letter U With DiaeresisC3 9C
1559B10011011¢U+00A2Cent SignC2 A2
1569C10011100£U+00A3Pound SignC2 A3
1579D10011101¥U+00A5Yen SignC2 A5
1589E10011110U+20A7Peseta SignE2 82 A7
1599F10011111ƒU+0192Latin Small Letter F With HookC6 92
160A010100000áU+00E1Latin Small Letter A With AcuteC3 A1
161A110100001íU+00EDLatin Small Letter I With AcuteC3 AD
162A210100010óU+00F3Latin Small Letter O With AcuteC3 B3
163A310100011úU+00FALatin Small Letter U With AcuteC3 BA
164A410100100ñU+00F1Latin Small Letter N With TildeC3 B1
165A510100101ÑU+00D1Latin Capital Letter N With TildeC3 91
166A610100110ªU+00AAFeminine Ordinal IndicatorC2 AA
167A710100111ºU+00BAMasculine Ordinal IndicatorC2 BA
168A810101000¿U+00BFInverted Question MarkC2 BF
169A910101001U+2310Reversed Not SignE2 8C 90
170AA10101010¬U+00ACNot SignC2 AC
171AB10101011½U+00BDVulgar Fraction One HalfC2 BD
172AC10101100¼U+00BCVulgar Fraction One QuarterC2 BC
173AD10101101¡U+00A1Inverted Exclamation MarkC2 A1
174AE10101110«U+00ABLeft-Pointing Double Angle Quotation MarkC2 AB
175AF10101111»U+00BBRight-Pointing Double Angle Quotation MarkC2 BB
176B010110000U+2591Light ShadeE2 96 91
177B110110001U+2592Medium ShadeE2 96 92
178B210110010U+2593Dark ShadeE2 96 93
179B310110011U+2502Box Drawings Light VerticalE2 94 82
180B410110100U+2524Box Drawings Light Vertical And LeftE2 94 A4
181B510110101U+2561Box Drawings Vertical Single And Left DoubleE2 95 A1
182B610110110U+2562Box Drawings Vertical Double And Left SingleE2 95 A2
183B710110111U+2556Box Drawings Down Double And Left SingleE2 95 96
184B810111000U+2555Box Drawings Down Single And Left DoubleE2 95 95
185B910111001U+2563Box Drawings Double Vertical And LeftE2 95 A3
186BA10111010U+2551Box Drawings Double VerticalE2 95 91
187BB10111011U+2557Box Drawings Double Down And LeftE2 95 97
188BC10111100U+255DBox Drawings Double Up And LeftE2 95 9D
189BD10111101U+255CBox Drawings Up Double And Left SingleE2 95 9C
190BE10111110U+255BBox Drawings Up Single And Left DoubleE2 95 9B
191BF10111111U+2510Box Drawings Light Down And LeftE2 94 90
192C011000000U+2514Box Drawings Light Up And RightE2 94 94
193C111000001U+2534Box Drawings Light Up And HorizontalE2 94 B4
194C211000010U+252CBox Drawings Light Down And HorizontalE2 94 AC
195C311000011U+251CBox Drawings Light Vertical And RightE2 94 9C
196C411000100U+2500Box Drawings Light HorizontalE2 94 80
197C511000101U+253CBox Drawings Light Vertical And HorizontalE2 94 BC
198C611000110U+255EBox Drawings Vertical Single And Right DoubleE2 95 9E
199C711000111U+255FBox Drawings Vertical Double And Right SingleE2 95 9F
200C811001000U+255ABox Drawings Double Up And RightE2 95 9A
201C911001001U+2554Box Drawings Double Down And RightE2 95 94
202CA11001010U+2569Box Drawings Double Up And HorizontalE2 95 A9
203CB11001011U+2566Box Drawings Double Down And HorizontalE2 95 A6
204CC11001100U+2560Box Drawings Double Vertical And RightE2 95 A0
205CD11001101U+2550Box Drawings Double HorizontalE2 95 90
206CE11001110U+256CBox Drawings Double Vertical And HorizontalE2 95 AC
207CF11001111U+2567Box Drawings Up Single And Horizontal DoubleE2 95 A7
208D011010000U+2568Box Drawings Up Double And Horizontal SingleE2 95 A8
209D111010001U+2564Box Drawings Down Single And Horizontal DoubleE2 95 A4
210D211010010U+2565Box Drawings Down Double And Horizontal SingleE2 95 A5
211D311010011U+2559Box Drawings Up Double And Right SingleE2 95 99
212D411010100U+2558Box Drawings Up Single And Right DoubleE2 95 98
213D511010101U+2552Box Drawings Down Single And Right DoubleE2 95 92
214D611010110U+2553Box Drawings Down Double And Right SingleE2 95 93
215D711010111U+256BBox Drawings Vertical Double And Horizontal SingleE2 95 AB
216D811011000U+256ABox Drawings Vertical Single And Horizontal DoubleE2 95 AA
217D911011001U+2518Box Drawings Light Up And LeftE2 94 98
218DA11011010U+250CBox Drawings Light Down And RightE2 94 8C
219DB11011011U+2588Full BlockE2 96 88
220DC11011100U+2584Lower Half BlockE2 96 84
221DD11011101U+258CLeft Half BlockE2 96 8C
222DE11011110U+2590Right Half BlockE2 96 90
223DF11011111U+2580Upper Half BlockE2 96 80
224E011100000αU+03B1Greek Small Letter AlphaCE B1
225E111100001ßU+00DFLatin Small Letter Sharp SC3 9F
226E211100010ΓU+0393Greek Capital Letter GammaCE 93
227E311100011πU+03C0Greek Small Letter PiCF 80
228E411100100ΣU+03A3Greek Capital Letter SigmaCE A3
229E511100101σU+03C3Greek Small Letter SigmaCF 83
230E611100110µU+00B5Micro SignC2 B5
231E711100111τU+03C4Greek Small Letter TauCF 84
232E811101000ΦU+03A6Greek Capital Letter PhiCE A6
233E911101001ΘU+0398Greek Capital Letter ThetaCE 98
234EA11101010ΩU+03A9Greek Capital Letter OmegaCE A9
235EB11101011δU+03B4Greek Small Letter DeltaCE B4
236EC11101100U+221EInfinityE2 88 9E
237ED11101101φU+03C6Greek Small Letter PhiCF 86
238EE11101110εU+03B5Greek Small Letter EpsilonCE B5
239EF11101111U+2229IntersectionE2 88 A9
240F011110000U+2261Identical ToE2 89 A1
241F111110001±U+00B1Plus-Minus SignC2 B1
242F211110010U+2265Greater-Than Or Equal ToE2 89 A5
243F311110011U+2264Less-Than Or Equal ToE2 89 A4
244F411110100U+2320Top Half IntegralE2 8C A0
245F511110101U+2321Bottom Half IntegralE2 8C A1
246F611110110÷U+00F7Division SignC3 B7
247F711110111U+2248Almost Equal ToE2 89 88
248F811111000°U+00B0Degree SignC2 B0
249F911111001U+2219Bullet OperatorE2 88 99
250FA11111010·U+00B7Middle DotC2 B7
251FB11111011U+221ASquare RootE2 88 9A
252FC11111100U+207FSuperscript Latin Small Letter NE2 81 BF
253FD11111101²U+00B2Superscript TwoC2 B2
254FE11111110U+25A0Black SquareE2 96 A0
255FF11111111 U+00A0No-Break SpaceC2 A0

ASCII and Unicode#

Unicode assigns a number, called a code point and written U+ followed by hex, to every character in every script. It currently defines about 155,000 of them, with room for 1,114,112. The first 128 Unicode code points are exactly ASCII, deliberately and permanently:

'A'  ASCII 65  =  U+0041
'~'  ASCII 126 =  U+007E

So ASCII is a subset of Unicode. What changes is how those code points become bytes, which is the job of an encoding.

UTF-8#

UTF-8 encodes a code point as one to four bytes, and it was designed specifically so that ASCII would survive untouched:

Code point rangeBytesBit pattern
U+0000 to U+007F10xxxxxxx
U+0080 to U+07FF2110xxxxx 10xxxxxx
U+0800 to U+FFFF31110xxxx 10xxxxxx 10xxxxxx
U+10000 to U+10FFFF411110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Read off the consequences:

Worked example, the euro sign U+20AC:

U+20AC = 0010 0000 1010 1100          (16 bits, so three bytes)
split:    0010     000010     101100
prefix:  1110xxxx 10xxxxxx 10xxxxxx
result:  11100010 10000010 10101100
hex:     E2       82       AC

Encoding a file, and what goes wrong#

"café".encode("utf-8")      # b'caf\xc3\xa9'   4 characters, 5 bytes
"café".encode("latin-1")    # b'caf\xe9'       4 characters, 4 bytes
"café".encode("ascii")      # UnicodeEncodeError: ordinal not in range(128)

The classic failure is text encoded as UTF-8 and decoded as Windows-1252. Each byte above 127 gets shown separately, so one character becomes two or three:

IntendedUTF-8 bytesRead as Windows-1252
éC3 A9é
E2 80 99’
E2 82 AC€

If you see à or †in output, that pattern is the diagnosis: UTF-8 bytes read as a single-byte code page. The fix is at the point of decoding, not by find-and-replace on the damaged text.

Escape sequences#

Because control characters cannot be typed into a string literal, every language provides backslash escapes. The common core came from C and has been copied almost everywhere.

EscapeCharacterDecC and C++PythonJavaJavaScriptGo
\0NUL0yesyesyes (octal)yes\x00
\aBell7yesyesnonoyes
\bBackspace8yesyesyesyesyes
\tTab9yesyesyesyesyes
\nLine feed10yesyesyesyesyes
\vVertical tab11yesyesnoyesyes
\fForm feed12yesyesyesyesyes
\rCarriage return13yesyesyesyesyes
\eEscape27GNU extensionnononono
\"Double quote34yesyesyesyesyes
\'Apostrophe39yesyesyesyesyes
\\Backslash92yesyesyesyesyes
\xHHHex byteanyyesyesnoyesyes
\nnnOctalanyyesyesyesdeprecatedyes
\uXXXXUnicode, 4 hexany\uXXXXyesyesyesyes

Where a language has no \e, write \x1b in C-family languages, \033 where octal is supported, or \u001b in Java. Python and JavaScript both accept \x1b, \033 and \u001b.

ANSI escape codes#

The most visible modern use of a control character. ESC (27) followed by [ starts a Control Sequence Introducer, and terminals interpret what follows as a command rather than text. This is how every coloured command line tool works.

The sequence is written ESC [ in prose, \033[ in C and shell, \x1b[ in Python and JavaScript, and shows up as ^[[ when a terminal prints it literally.

Colours and styles#

Set Graphic Rendition takes one or more numbers separated by semicolons and ends with m.

CodeEffectCodeEffect
0Reset everything30-37Foreground black, red, green, yellow, blue, magenta, cyan, white
1Bold or bright40-47Background, same eight colours
2Dim90-97Bright foreground
3Italic100-107Bright background
4Underline39Default foreground
7Reverse video49Default background
9Strikethrough38;5;n256-colour foreground, n is 0-255
22Normal intensity48;5;n256-colour background
24Underline off38;2;r;g;b24-bit foreground
27Reverse off48;2;r;g;b24-bit background
printf '\033[1;31merror\033[0m: something broke\n'   # bold red word
printf '\033[38;2;255;140;0morange\033[0m\n'         # true colour

Always emit the reset (\033[0m) or the styling leaks into whatever the terminal prints next.

Cursor and screen control#

SequenceEffect
ESC [ n ACursor up n rows
ESC [ n BCursor down n rows
ESC [ n CCursor right n columns
ESC [ n DCursor left n columns
ESC [ r ; c HMove cursor to row r, column c, counting from 1
ESC [ 2 JClear the whole screen
ESC [ KClear from the cursor to the end of the line
ESC [ sSave the cursor position
ESC [ uRestore the saved cursor position
ESC [ ? 25 lHide the cursor
ESC [ ? 25 hShow the cursor

Combining carriage return with "clear to end of line" is how progress bars redraw in place: \r\033[K puts you back at column one and wipes what was there.

Practical gotchas#

Things that cost people real time:

  1. char may be signed. In C, plain char is signed on most platforms, so a byte above 127 becomes negative. Passing it to isalpha or toupper is undefined behaviour. Cast to unsigned char first: toupper((unsigned char) c).
  2. The Backspace key sends DEL, not BS. Code 127, not code 8. Terminal configuration (stty erase) decides, and mismatches are why backspace sometimes prints ^? over SSH.
  3. \n is not always one byte on disk. On Windows, text mode translates it to CRLF on write. If you compute a file length from string lengths, it will be wrong.
  4. A trailing \r is invisible. Compare strings after stripping, and if a comparison fails for no visible reason, print repr() of both sides.
  5. Curly quotes are not ASCII. " from a word processor is U+201C, not code 34. Pasting code from a document produces syntax errors that look like nothing is wrong.
  6. No-break space is not space. U+00A0 survives copy and paste from web pages, looks identical, and fails == " " and often strip().
  7. Sorting is not alphabetical. Byte order puts all uppercase before all lowercase, and puts digits before letters. Use a locale-aware collation for anything a user will read.
  8. NUL terminates C strings. Any data containing a zero byte cannot round-trip through a char * API. This is a real security issue when a language that allows embedded NULs hands a string to a C library that does not.
  9. isdigit is not isdigit in Unicode. Python's str.isdigit() returns true for superscripts and other scripts' digits. Use str.isascii() and str.isdigit() if you mean the ASCII ten.
  10. Case conversion is not always a bit flip. Turkish dotless i, German sharp s and Greek final sigma all break the assumption that case changes one character to one character. Only the ASCII range is safe.

Where ASCII shows up#

Base64#

Base64 exists to push arbitrary binary through channels that only survive ASCII, such as email bodies and URLs. It takes three bytes (24 bits) at a time, splits them into four 6-bit groups, and maps each group to one of 64 printable characters. Output is therefore about 33 percent larger than the input, and it is padded with = to a multiple of four.

The standard Base64 alphabet (RFC 4648)
ValCharValCharValCharValChar
0A16Q32g48w
1B17R33h49x
2C18S34i50y
3D19T35j51z
4E20U36k520
5F21V37l531
6G22W38m542
7H23X39n553
8I24Y40o564
9J25Z41p575
10K26a42q586
11L27b43r597
12M28c44s608
13N29d45t619
14O30e46u62+
15P31f47v63/

The URL-safe variant of RFC 4648 replaces + with - and / with _, so the result can go in a query string or filename without escaping.

Percent encoding in URLs#

RFC 3986 splits ASCII into characters a URL may contain literally and characters that must be written as % followed by two hex digits.

ClassCharactersIn a URL
UnreservedA-Z a-z 0-9 - . _ ~Always safe, never needs encoding
Reserved, generic: / ? # [ ] @Safe only in their structural role
Reserved, sub-delimiters! $ & ' ( ) * + , ; =Encode inside a value
Everything elsespace, ", <, >, \, ^, backtick, {, |, }, and all controlsMust be percent-encoded

Space is %20, or + in the older application/x-www-form-urlencoded form-data format only. # is %23, & is %26, and % itself is %25.

Regular expression character classes#

POSIX classes map directly onto ranges of this table, which is worth seeing written out:

ClassASCII rangeEquivalent
[:digit:]48-57[0-9]
[:upper:]65-90[A-Z]
[:lower:]97-122[a-z]
[:alpha:]65-90, 97-122[A-Za-z]
[:alnum:]48-57, 65-90, 97-122[0-9A-Za-z]
[:xdigit:]48-57, 65-70, 97-102[0-9A-Fa-f]
[:punct:]33-47, 58-64, 91-96, 123-126Printable, not alphanumeric, not space
[:space:]9-13, 32[ \t\n\v\f\r]
[:cntrl:]0-31, 127The control characters
[:print:]32-126Everything with a visible form, plus space
[:graph:]33-126Printable excluding space
[:ascii:]0-127The whole table

Note that \w in most engines means [A-Za-z0-9_], which includes the underscore. In Unicode-aware mode it means far more than that, so \w and [:alpha:] are not interchangeable.

Other places it hangs around#

A short history#

Two names are worth attaching to the design. The 32 gap between cases and the placement of the control characters were chosen so that the encoding would be easy to manipulate with the simple logic circuits of the early 1960s, and the same choices are what make the bit tricks on this page work sixty years later. Good encodings age well.

Glossary#

TermMeaning
ASCIIAmerican Standard Code for Information Interchange. A 7-bit code defining 128 characters.
ByteEight bits on any machine you will use. Historically the size varied, which is why network standards say "octet".
Character setThe collection of characters and the numbers assigned to them.
Code pageAn older term, mostly IBM and Microsoft, for a particular 8-bit character set such as CP437 or CP1252.
Code pointThe number assigned to a character. ASCII has 128, Unicode has room for 1,114,112.
Code unitThe fixed-size piece an encoding works in: 8 bits for UTF-8, 16 for UTF-16.
CollationThe rules for ordering strings for a human reader, as opposed to sorting by byte value.
Control characterA code point that commands a device rather than representing a printable symbol.
EBCDICIBM's competing 8-bit mainframe encoding, in which the alphabet is not contiguous. Still alive on z/OS.
EncodingThe rule turning code points into bytes. ASCII, UTF-8 and Latin-1 are all encodings.
GlyphThe drawn shape of a character in a particular font. One character can have many glyphs.
MojibakeText made unreadable by decoding it with the wrong encoding. Japanese for "character transformation".
OctetExactly eight bits. Used in standards documents where "byte" would be ambiguous.
Parity bitThe eighth bit on a 7-bit serial link, set so the total number of set bits is odd or even, giving basic error detection.
NibbleFour bits, that is one hex digit.
UnicodeThe universal character set that ASCII is now the first 128 characters of.
UTF-8The variable-width encoding of Unicode that is backwards compatible with ASCII.

Further reading#