ord() Function in Python (With Examples)

The ord() function in Python takes a single character and returns its Unicode code point, an integer. chr() does the reverse, so the two always round-trip:

ord("A")      # 65
chr(65)       # 'A'
ord("€")      # 8364

I ran each example on Python 3.12.5 in a Windows Command Prompt, including the accented characters and symbols, so the numbers you see are exactly what Python returned.

You’ll see the codes for common characters, non-English text, the TypeError that trips people up, and practical uses: letter positions, a Caesar cipher and why sorting puts capitals first.

How ord() and chr() work

Every character has a number. For plain English letters, digits and punctuation, that number is the same as the old ASCII code:

for ch in ["A", "a", "Z", "0", " ", "$"]:
    print(f"ord({ch!r}) = {ord(ch)}")

print(chr(65), chr(97), chr(36))          # chr() goes the other way
print(chr(ord("A") + 1))                  # the next letter

Output:

ord('A') = 65
ord('a') = 97
ord('Z') = 90
ord('0') = 48
ord(' ') = 32
ord('$') = 36
A a $
B
Command Prompt output of Python ord on uppercase and lowercase letters, a digit, a space and a dollar sign, plus chr converting back
Uppercase A is 65, lowercase a is 97, and chr() turns the numbers back into characters.

chr(ord("A") + 1) is a neat way to get the next letter. The chr() function in Python covers the reverse direction in more depth.

ord() with accented letters and symbols

ord() isn’t limited to ASCII. It returns the full Unicode code point, which you’ll usually see written as U+ followed by hex digits:

for ch in ["é", "ñ", "€", "©", "°"]:
    code = ord(ch)
    print(f"{ch}  ord = {code:>5}   U+{code:04X}   UTF-8 bytes: {len(ch.encode('utf-8'))}")

Output:

é  ord =   233   U+00E9   UTF-8 bytes: 2
ñ  ord =   241   U+00F1   UTF-8 bytes: 2
€  ord =  8364   U+20AC   UTF-8 bytes: 3
©  ord =   169   U+00A9   UTF-8 bytes: 2
°  ord =   176   U+00B0   UTF-8 bytes: 2
Command Prompt output of Python ord on accented letters and symbols with their Unicode code points in hex and UTF-8 byte counts
The euro sign is code point 8364, or U+20AC, and takes three bytes in UTF-8.

The code point and the number of bytes are different things: the code point identifies the character, and the encoding decides how it’s stored. To check whether text is plain ASCII, see checking if a string is ASCII.

TypeError: ord() expected a character, but string of length found

ord() accepts exactly one character. Pass a longer string, or an empty one, and you get a TypeError that tells you the length it received:

for text in ["A", "abc", ""]:
    try:
        print(repr(text), "->", ord(text))
    except TypeError as err:
        print(repr(text), "-> TypeError:", err)

print([ord(ch) for ch in "abc"])          # one code per character

Output:

'A' -> 65
'abc' -> TypeError: ord() expected a character, but string of length 3 found
'' -> TypeError: ord() expected a character, but string of length 0 found
[97, 98, 99]
Command Prompt output of Python ord raising TypeError for a three-character string and an empty string
One character works. Three characters or none raise TypeError.

To get codes for a whole string, loop over it: [ord(ch) for ch in text]. Converting a string to ASCII has more ways to do that.

Using ord() to get a letter’s position in the alphabet

Because letters have consecutive codes, subtracting ord("a") gives a letter’s position. Lowercase first so capitals work too:

def letter_position(ch):
    """A/a -> 1, B/b -> 2, ... Z/z -> 26."""
    return ord(ch.lower()) - ord("a") + 1

print([letter_position(c) for c in "Texas"])

def is_upper_ascii(ch):
    return ord("A") <= ord(ch) <= ord("Z")

print(is_upper_ascii("T"), is_upper_ascii("t"), "T".isupper())

Output:

[20, 5, 24, 1, 19]
True False True

For checks like “is it uppercase”, the string methods such as isupper() are clearer and also handle non-English letters. Converting letters to numbers covers other approaches.

A Caesar cipher with ord() and chr()

Shifting letters is the classic ord() exercise. Convert to a number, shift, wrap around with % 26, and convert back:

def shift(text, n):
    out = []
    for ch in text:
        if "a" <= ch <= "z":
            out.append(chr((ord(ch) - ord("a") + n) % 26 + ord("a")))
        elif "A" <= ch <= "Z":
            out.append(chr((ord(ch) - ord("A") + n) % 26 + ord("A")))
        else:
            out.append(ch)               # leave spaces and punctuation alone
    return "".join(out)

secret = shift("Meet in Austin at noon", 3)
print(secret)
print(shift(secret, -3))

Output:

Phhw lq Dxvwlq dw qrrq
Meet in Austin at noon

It’s a toy, not real encryption, but it’s a good way to see why character codes are useful. The same shift-and-wrap idea shows up in checksums and simple encoding schemes.

Why do capital letters sort before lowercase in Python?

Python compares strings by their code points, character by character. Every capital letter has a smaller code than every lowercase one, so plain sorting puts capitals first:

cities = ["denver", "Austin", "boston", "Chicago"]

print(sorted(cities))                    # capitals first: 'C' (67) < 'b' (98)
print(sorted(cities, key=str.lower))     # alphabetical, ignoring case

print("'Z' < 'a':", "Z" < "a", "|", ord("Z"), "<", ord("a"))
print(ord("5"), "is not", int("5"))      # a digit's code isn't its value

Output:

['Austin', 'Chicago', 'boston', 'denver']
['Austin', 'boston', 'Chicago', 'denver']
'Z' < 'a': True | 90 < 97
53 is not 5
Command Prompt output showing Python sorted placing capitalized city names first because uppercase code points are smaller, and key=str.lower fixing it
“Chicago” lands before “boston” because C is 67 and b is 98. key=str.lower sorts the way people expect.

The last line is a common slip with digits: ord("5") is 53, not 5. Use int("5") when you want a digit’s value.

ord() in Python: quick reference

GoalCodeResult
Code of a characterord("A")65
Character from a codechr(65)‘A’
Next letterchr(ord("A") + 1)‘B’
Position in the alphabetord(c.lower()) - ord("a") + 11 to 26
Codes for a whole string[ord(c) for c in text]a list of ints
Unicode notationf"U+{ord(c):04X}"‘U+20AC’ for €
Case-insensitive sortsorted(words, key=str.lower)alphabetical

More guides on characters and text in Python:

Frequently asked questions

What does ord() do in Python?

It returns the Unicode code point of a single character as an integer. ord("A") is 65.

What is the opposite of ord() in Python?

chr(). It takes a code point and returns the character, so chr(ord(c)) == c for any character.

Is ord() the same as ASCII?

For the first 128 characters, yes: Unicode code points match ASCII codes there. Beyond that, ord() returns Unicode values like 233 for é.

Why does ord() say ‘expected a character, but string of length 3 found’?

You passed a string with more than one character. Use [ord(c) for c in text] to convert each one.

How do I get the position of a letter in the alphabet?

Use ord(c.lower()) - ord("a") + 1, which gives 1 for a and 26 for z.

Can ord() handle emoji?

Yes, if the emoji is a single code point. Some emoji are built from several code points, which makes them strings of length greater than one. The ord() documentation describes the exact rule.