ASCII Code Explorer
Visualize how text characters are represented as numerical codes in computers.
Character Representations
0 CHARSEnter text to see ASCII codes
Tip: ASCII encodes 128 specified characters into 7-bit integers.
Visualize how text characters are represented as numerical codes in computers.
Enter text to see ASCII codes
Tip: ASCII encodes 128 specified characters into 7-bit integers.
ASCII, which stands for American Standard Code for Data Interchange, is a character encoding standard. In simple terms, it's a universal dictionary that assigns a unique number to each letter, digit, and symbol you can type. Computers don't understand letters like 'A' or 'b'. They only understand numbers. ASCII translates our human-readable characters into a numeric format. The standard sets 128 characters using 7 bits. Codes 0-31 are control characters (newline, tab, carriage return), 32-47 and 58-64 are punctuation and symbols, 48-57 are the digits 0-9, 65-90 are uppercase A-Z, and 97-122 are lowercase a-z. The gap of just 32 between uppercase and lowercase is deliberate. Flipping one bit (bit 5) converts between cases. This is why chr(ord('A') + 32) gives 'a' and ord('a') - ord('A') gives 32. This bit trick appears in interview problems that ask for case-insensitive checks without library functions. ASCII uses only 7 of 8 bits in a byte. This leaves the high bit free. Extended ASCII (codes 128-255) uses that bit for accented characters, but different systems set different extensions. This leads to the encoding chaos that Unicode was created to resolve. UTF-8, the dominant encoding today, is backwards-compatible: each ASCII character has the same byte value in UTF-8. So pure-ASCII text is valid UTF-8 without any conversion. This page shows the ASCII table, converts text to codes and back, and covers the uppercase-lowercase bit trick.
Visualize how text characters are represented as numerical codes in computers.
Explore how every character you type is converted into a universal numerical code that computers can understand.
ASCII, which stands for American Standard Code for Data Interchange, is a character encoding standard. In simple terms, it's a universal dictionary that assigns a unique number to each letter, digit, and symbol you can type. Computers don't understand letters like 'A' or 'b'. They only understand numbers. ASCII translates our human-readable characters into a numeric format. The standard sets 128 characters using 7 bits. Codes 0-31 are control characters (newline, tab, carriage return), 32-47 and 58-64 are punctuation and symbols, 48-57 are the digits 0-9, 65-90 are uppercase A-Z, and 97-122 are lowercase a-z. The gap of just 32 between uppercase and lowercase is deliberate. Flipping one bit (bit 5) converts between cases. This is why chr(ord('A') + 32) gives 'a' and ord('a') - ord('A') gives 32. This bit trick appears in interview problems that ask for case-insensitive checks without library functions. ASCII uses only 7 of 8 bits in a byte. This leaves the high bit free. Extended ASCII (codes 128-255) uses that bit for accented characters, but different systems set different extensions. This leads to the encoding chaos that Unicode was created to resolve. UTF-8, the dominant encoding today, is backwards-compatible: each ASCII character has the same byte value in UTF-8. So pure-ASCII text is valid UTF-8 without any conversion. This page shows the ASCII table, converts text to codes and back, and covers the uppercase-lowercase bit trick.
The standard ASCII table holds 128 unique codes, numbered from 0 to 127. Each code represents a set character. For case:
'A' is assigned the ASCII code 65.'a' is assigned the ASCII code 97.'5' is assigned the ASCII code 53.' ' is assigned the ASCII code 32.When you type "Hello", the computer sees the sequence of numbers: 72, 101, 108, 108, 111.
Computers store numbers. ASCII was the agreement, from 1963, about which number means. This character — 128 codes covering the English alphabet, digits, punctuation and control characters.
| Character | Decimal | Hex |
|---|---|---|
NUL | 0 | 00 |
\n (newline) | 10 | 0A |
| space | 32 | 20 |
0 | 48 | 30 |
A | 65 | 41 |
Z | 90 | 5A |
a | 97 | 61 |
z | 122 | 7A |
Three of those ranges are worth memorising because they make arithmetic tricks doable.
Digits start at 48, so ord('7') - ord('0') gives 7. Converting a character to its numeric value without a lookup table.
Uppercase starts at 65 and lowercase at 97, just 32 apart. So chr(ord('A') + 32) is 'a', and since 32 is a single bit (2⁵), case conversion is a bit flip —. This is why it was historically so cheap.
Letters are contiguous, so 'a' <= c <= 'z' tests for a lowercase letter, and sorting strings by code point sorts alphabetically within a case.
ord('A') # 65
chr(97) # 'a'
ord('a') - ord('A') # 32
'A' < 'a' # True - uppercase sorts firstThat last line is a real source of surprise. Sorting a list of names puts each capitalised entry before each lowercase one, because 'Z' (90) is less than 'a' (97).
ASCII covers English. It has no é, no ñ, no ö, no Cyrillic, no Greek, no Arabic, no Chinese, no emoji.
The first response was a proliferation of 8-bit extensions. Latin-1 for Western European, Windows-1252, KOI8-R for Russian, and dozens more. Each redefining codes 128–255 differently. A file was only readable if you knew which encoding it used. And the classic symptom of guessing wrong is text like "é" where "é" should be.
Unicode is the modern answer: one code point per character. This covers each script, now over 149,000 assigned. é is U+00E9, 中 is U+4E2D, and 🎉 is U+1F389.
Unicode assigns numbers; it does not say how to store them. That is what an encoding does, and UTF-8 is the one that won:
| Character | Code point | UTF-8 bytes |
|---|---|---|
A | U+0041 | 1 byte: 41 |
é | U+00E9 | 2 bytes: C3 A9 |
中 | U+4E2D | 3 bytes: E4 B8 AD |
| 🎉 | U+1F389 | 4 bytes: F0 9F 8E 89 |
UTF-8's decisive property is that the first 128 code points encode as single bytes the same to ASCII. Each ASCII file is already valid UTF-8, which is why adoption was doable at all.
Characters are not bytes. len("café") is 4 characters and 5 UTF-8 bytes. Truncating a string at a byte boundary can split a character in half and give invalid data. A real bug when enforcing length limits on user input.
The same text can have two encodings. "é" may be one code point (U+00E9) or two (e + combining accent U+0301). They look the same and compare as different strings, which is the most common cause of "these records should match and do not". unicodedata.normalize("NFKC", text) resolves it, and should be the first step of any text pipeline.
Tokenisers work on bytes or characters. Byte-level BPE, used by GPT models, operates on UTF-8 bytes. So it can represent any text at all. At the cost of more tokens for non-Latin scripts, since each character consumes a few bytes.
Encoding errors are silent or fatal. Reading a UTF-8 file as Latin-1 succeeds and gives mojibake; reading a Latin-1 file as UTF-8 raises UnicodeDecodeError. Always specify the encoding by name.
Each string is bytes, and the mapping from bytes to characters is where a surprising amount of NLP goes wrong. ASCII, Unicode and UTF-8 are all inspected here right.
Unicode extends the same idea to each writing system. Here is how code points, UTF-8 bytes, and string length relate.
The normalisation trap: two byte sequences that look the same on screen can compare as unequal. And that is why models prefer bytes.
Use the "ASCII Code Explorer" above to see this process in action:
ASCII is a foundational concept in Natural Language Handling (NLP). While modern systems often use more advanced encodings like UTF-8 to support emojis and multiple languages, the core principle remains the same. Text must be converted to numbers for a machine to process it. Grasp ASCII helps you grasp basic NLP tasks:
ASCII is the key bridge between human language and computer handling. It standardizes the form of text as numbers, a basic step for all digital communication and work. By linking with the explorer, you can build a solid intuition for this cornerstone of computer science and NLP.
# always specify the encoding
with open("data.txt", encoding="utf-8") as f:
text = f.read()
# be explicit about failures
text = raw_bytes.decode("utf-8", errors="replace") # bad bytes become U+FFFD
text = raw_bytes.decode("utf-8", errors="ignore") # bad bytes dropped
# normalise before comparing
import unicodedata
a = unicodedata.normalize("NFKC", a)
b = unicodedata.normalize("NFKC", b)
a == bPython 3 keeps this straight by separating the two types: str is a sequence of Unicode code points, bytes is a sequence of 8-bit values. You cannot concatenate them, which prevents a whole class of bug that Python 2 permitted.
The four normalisation forms: NFC composes characters where doable, NFD decomposes them, and NFKC/NFKD also fold support variants (full-width characters, ligatures, superscripts). NFKC is the usual choice for text handling, because it collapses the largest number of visually-the same forms.
Control characters take codes 0–31 and 127. Most are historical — bell, form feed, device control — and their presence in scraped text often shows a problem. Strip them.
Line endings differ. Unix uses \n (10), Windows uses \r\n (13, 10). Reading in text mode normalises them; reading in binary mode does not, and stray \r characters at line ends are a common annoyance.
Zero-width and invisible characters exist and cause trouble: zero-width space (U+200B), zero-width joiner, byte-order mark (U+FEFF). A BOM at the start of a file appears as an invisible character in the first field. This breaks header parsing in CSV files — encoding="utf-8-sig" strips it.
Emoji are often a few code points. A single visible emoji may combine a base character, a skin-tone modifier and a zero-width joiner. So len() on an emoji string rarely matches what the user sees.
Is ASCII still apt? As a subset of UTF-8, yes. And never as a complete encoding for real-world text.
Why is 'A' < 'a'? Because 65 < 97. Sorting by code point puts all uppercase before all lowercase.
What is mojibake? Text decoded with the wrong encoding — "café" appearing as "café". The fix is to find the true encoding, not to patch the symptoms.
Should I always use UTF-8? Yes, for output. For input, detect or be told; chardet guesses when nothing else is available.
Why does my string length look wrong? Characters, bytes and user-perceived characters are three different counts. Emoji and combining accents make them diverge.
What is a byte-order mark? An invisible marker at the start of a file showing the encoding. Harmless in principle, and it corrupts the first field of a CSV; use utf-8-sig to strip it.
Say the answer out loud before you reveal it — recalling it is what makes it stick, and rereading it is not.
Without scrolling back — what is the one-line takeaway from this module?
What does this module say about “What is ASCII”?
What does this module say about “How It Works: From Character to Code”?
Type any character and see the ASCII number a computer actually stores, the very first step from text into numbers.