Toolmingo
Guides10 min read

What Is ASCII? The Character Encoding Every Developer Should Know

Learn what ASCII is, how it works, what the 128 ASCII codes represent, and how it relates to Unicode and UTF-8. Includes ASCII table and code examples in JavaScript, Python, Go, and PHP.

Open a terminal and type man ascii. You'll get a table of 128 symbols, each paired with a number. That table is ASCII — the bedrock that every text file, HTTP header, email, JSON document, and source code file is built on.

What does ASCII stand for?

ASCII stands for American Standard Code for Information Interchange. It was published in 1963 and standardised in 1968. The goal was simple: make sure a teletype machine made by one company could talk to a computer made by another.

ASCII encodes 128 characters using 7 bits (0–127). Each character maps to a unique integer — its code point. A capital A is always 65. A space is always 32. A newline is always 10. This fixed mapping is what makes plain text portable.

The 128 ASCII characters

ASCII has three groups:

Range Group Examples
0–31 Control characters (non-printable) NUL (0), LF (10), CR (13), ESC (27)
32–126 Printable characters space, letters, digits, punctuation
127 Delete (DEL) Non-printable control character

Printable ASCII quick reference

Dec Hex Char Dec Hex Char Dec Hex Char
32 20 (space) 64 40 @ 96 60 `
33 21 ! 65 41 A 97 61 a
34 22 " 66 42 B 98 62 b
35 23 # 67 43 C 99 63 c
36 24 $ 68 44 D 100 64 d
37 25 % 69 45 E 101 65 e
38 26 & 70 46 F 102 66 f
39 27 ' 71 47 G 103 67 g
40 28 ( 72 48 H 104 68 h
41 29 ) 73 49 I 105 69 i
42 2A * 74 4A J 106 6A j
43 2B + 75 4B K 107 6B k
44 2C , 76 4C L 108 6C l
45 2D - 77 4D M 109 6D m
46 2E . 78 4E N 110 6E n
47 2F / 79 4F O 111 6F o
48 30 0 80 50 P 112 70 p
49 31 1 81 51 Q 113 71 q
50 32 2 82 52 R 114 72 r
51 33 3 83 53 S 115 73 s
52 34 4 84 54 T 116 74 t
53 35 5 85 55 U 117 75 u
54 36 6 86 56 V 118 76 v
55 37 7 87 57 W 119 77 w
56 38 8 88 58 X 120 78 x
57 39 9 89 59 Y 121 79 y
58 3A : 90 5A Z 122 7A z
59 3B ; 91 5B [ 123 7B {
60 3C < 92 5C \ 124 7C |
61 3D = 93 5D ] 125 7D }
62 3E > 94 5E ^ 126 7E ~
63 3F ? 95 5F _

Useful patterns to memorise:

  • A = 65, a = 97 — lowercase is uppercase + 32
  • 0 = 48 — digit n is 48 + n
  • Space = 32, the lowest printable character

Key control characters

Control characters (0–31) are invisible but essential:

Code Name Meaning
0 NUL Null — string terminator in C
9 HT Horizontal tab
10 LF Line feed (Unix newline \n)
13 CR Carriage return (\r, part of Windows \r\n)
27 ESC Escape — starts ANSI terminal sequences
32 SP Space (first printable character)

ASCII vs Unicode vs UTF-8

ASCII works for English text. The moment you need é, ñ, , or 🎉, you need more than 128 slots.

Standard Code points Bytes per character Covers
ASCII 128 1 (7 bits) English + basic punctuation
Latin-1 (ISO 8859-1) 256 1 (8 bits) Western European languages
Unicode 1,114,112 1–4 (varies by encoding) Every human script + emoji
UTF-8 (Unicode) 1–4 Unicode; ASCII-compatible for code points 0–127

The key insight: UTF-8 is a superset of ASCII. Any file that contains only ASCII characters (code points 0–127) is a valid UTF-8 file. That's why ASCII-only source code, JSON, and HTML work transparently in UTF-8 environments.

Working with ASCII in code

JavaScript

// char → code point
"A".charCodeAt(0);       // 65
"a".charCodeAt(0);       // 97

// code point → char
String.fromCharCode(65); // "A"

// check if a character is printable ASCII
function isPrintableAscii(char) {
  const code = char.charCodeAt(0);
  return code >= 32 && code <= 126;
}

// convert string to array of ASCII codes
function toAsciiCodes(str) {
  return [...str].map(c => c.charCodeAt(0));
}

// uppercase → lowercase via ASCII arithmetic
function toLowerAscii(char) {
  const code = char.charCodeAt(0);
  if (code >= 65 && code <= 90) {
    return String.fromCharCode(code + 32);
  }
  return char;
}

console.log(toAsciiCodes("Hi!"));       // [72, 105, 33]
console.log(toLowerAscii("A"));         // "a"

Python

# char → code point
ord("A")               # 65
ord("a")               # 97

# code point → char
chr(65)                # "A"

# check printable ASCII
def is_printable_ascii(s: str) -> bool:
    return all(32 <= ord(c) <= 126 for c in s)

# string to list of ASCII codes
def to_ascii_codes(s: str) -> list[int]:
    return [ord(c) for c in s]

# print the printable ASCII table
for code in range(32, 127):
    print(f"{code:3d}  0x{code:02X}  {chr(code)!r}")

print(ord("Z") - ord("A"))  # 25 — gap between last and first letter
print(is_printable_ascii("hello!"))  # True
print(is_printable_ascii("héllo"))   # False — é is code point 233

Go

package main

import (
    "fmt"
    "unicode"
)

func isPrintableASCII(r rune) bool {
    return r >= 32 && r <= 126
}

func toASCIICodes(s string) []int {
    codes := make([]int, 0, len(s))
    for _, r := range s {
        codes = append(codes, int(r))
    }
    return codes
}

func main() {
    // char ↔ code point
    fmt.Println(int('A'))        // 65
    fmt.Println(string(rune(65))) // "A"

    // lowercase → uppercase via arithmetic
    c := 'a'
    if c >= 'a' && c <= 'z' {
        fmt.Println(string(c - 32)) // "A"
    }

    // Go's unicode package for classification
    fmt.Println(unicode.IsUpper('A'))   // true
    fmt.Println(unicode.IsDigit('7'))   // true
    fmt.Println(unicode.IsLetter('!'))  // false

    fmt.Println(toASCIICodes("Hi!"))    // [72 105 33]
}

PHP

<?php
// char → ASCII code
ord("A");          // 65
ord("a");          // 97

// code → char
chr(65);           // "A"

// check printable ASCII
function isPrintableAscii(string $s): bool {
    for ($i = 0; $i < strlen($s); $i++) {
        $code = ord($s[$i]);
        if ($code < 32 || $code > 126) {
            return false;
        }
    }
    return true;
}

// string to array of ASCII codes
function toAsciiCodes(string $s): array {
    $codes = [];
    for ($i = 0; $i < strlen($s); $i++) {
        $codes[] = ord($s[$i]);
    }
    return $codes;
}

print_r(toAsciiCodes("Hi!"));       // [72, 105, 33]
var_dump(isPrintableAscii("hello")); // bool(true)
var_dump(isPrintableAscii("héllo")); // bool(false)

Where you encounter ASCII every day

URL encoding replaces non-ASCII (and unsafe ASCII) characters with % + hex code. Space (32 = 0x20) becomes %20. See how to URL encode a string for the full rules.

HTML entities exist partly because ASCII characters like < (60) and & (38) have special meaning in HTML. &lt; (less-than) and &amp; (ampersand) are the safe substitutes. The HTML character entities guide covers all of them.

Base64 converts arbitrary binary data into a 64-character alphabet taken entirely from printable ASCII (A–Z, a–z, 0–9, +, /). That's why base64-encoded data is safe to embed in JSON, HTTP headers, and email bodies.

Hashing algorithms (MD5, SHA-256) output bytes that are typically displayed as lowercase hex — characters 0–9 and a–f, all printable ASCII.

Source code is almost always pure ASCII or UTF-8. Identifiers, keywords, operators, and string delimiters all live in the ASCII range, which is why an ASCII source file compiles identically on any machine.

Common pitfalls

1. Assuming one byte = one character
In ASCII that's true. In UTF-8 it's not — é is two bytes (0xC3 0xA9), is three, 🎉 is four. Use language-level string functions, not byte-level slicing, for Unicode strings.

2. Using strlen in PHP on multibyte strings
strlen("héllo") returns 6, not 5 — because é is two bytes. Use mb_strlen("héllo", "UTF-8") → 5.

3. Treating char as a byte in Go
In Go, a byte (alias uint8) and a rune (alias int32) are different. Ranging over a string with for i, b := range s gives runes; indexing with s[i] gives bytes. Mix them up and you'll corrupt multi-byte characters.

4. Confusing CR, LF, and CRLF
Unix uses LF (\n, code 10). Windows uses CRLF (\r\n, codes 13 + 10). Classic Mac OS used CR alone (\r, code 13). A file opened in binary mode will reveal these differences; most text editors and HTTP libraries handle conversion automatically.

5. Forgetting NUL in C strings
C strings are NUL-terminated: a string of 5 characters occupies 6 bytes, with the last byte being \0 (code 0). Omitting space for NUL is a classic buffer-overflow source.

6. Assuming ASCII-only input
Never assume user input is pure ASCII. Even a simple name field can contain ñ, ö, or ї. Validate and sanitise with Unicode-aware functions from the start.

Frequently asked questions

What is ASCII art?
ASCII art uses the 95 printable ASCII characters to draw pictures. Pioneered in the 1960s–70s when video terminals only displayed ASCII, it remains popular in terminal UIs, README files, and online culture.

Is ASCII still used today?
Yes, constantly. HTTP headers, JSON keys, email protocols (SMTP), domain names in their base form, programming language keywords, and most config files use only ASCII. Unicode and UTF-8 layer on top of it, not replace it.

What is the difference between ASCII and ANSI?
"ANSI" is often misused to mean Windows code page 1252 (or other 8-bit encodings). True ANSI standards include ASCII (ANSI X3.4-1968). When Windows Notepad calls its default encoding "ANSI", it means the system's legacy 8-bit code page — not pure ASCII and not Unicode.

Why does uppercase A start at 65 and not 1?
The first 32 slots (0–31) were reserved for control characters (NUL, BEL, CR, LF, ESC…). Space (32) comes next because it separates printable characters from control codes. Digits start at 48 so they align neatly with their hex equivalents (0x30–0x39). Letters were placed after punctuation partly for teletype compatibility.

Can I use ASCII to encrypt data?
No. A Caesar cipher or ROT13 rotates letters within the ASCII range but is trivially broken. For real encryption, use a proper algorithm like AES. For data integrity, use a hash (SHA-256). Neither is "encryption" in the cryptographic sense.

What is extended ASCII?
"Extended ASCII" refers to 8-bit encodings (code points 128–255) that different vendors defined differently: IBM used code page 437 for the original PC; Western European systems used Latin-1 (ISO 8859-1). They are not standardised and not compatible with each other. UTF-8 replaced them.

Related tools

Keep reading

All Toolmingotools are free & run in your browser

No sign-up, no upload, no watermark. Your files never leave your device.

Browse all tools