References

Beginner-friendly references for web development, with live, editable examples.

The HTML charset attribute

Attribute All modern browsers Updated
In short

The HTML charset attribute on <meta> declares the page's character encoding. Its only valid value is utf-8. Put <meta charset="utf-8"> within the first 1024 bytes of the document, ideally as the first element in <head>.

Overview

The charset attribute declares which character encoding a page's bytes use. On <meta> it acts as the document's character encoding declaration, and the HTML Standard allows exactly one value, a case-insensitive match for utf-8, so UTF-8 works too.

Placement matters as much as the value. The whole element must sit within the first 1024 bytes of the file, a document may contain only one such declaration, and it cannot be combined with <meta http-equiv="content-type">, the alternative form of the same declaration.

The browser checks several sources. The main ones, in order, are a byte order mark at the start of the file, a charset in the HTTP Content-Type header, and a meta tag found by pre-scanning the first bytes. If none of those exist, the browser guesses, and the fallback the HTML Standard suggests for many locales is windows-1252.

A wrong guess garbles text. The UTF-8 bytes for é read as windows-1252 come out as é, which is why the standard requires a declaration even on a page that is pure ASCII today, since form input and script-built URLs still need a known encoding.

Syntax

<head>
  <meta charset="utf-8">
  <title>Page title</title>
</head>

Values

Value
The string utf-8, matched case-insensitively. It is the only conforming value.

Example

Live example
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Café menu</title>
</head>
<body>
  <p>Café, crème brûlée, 20 °C</p>
  <p id="out"></p>
  <script>
    const bytes = new TextEncoder().encode('Café, crème brûlée, 20 °C');
    const wrong = new TextDecoder('windows-1252').decode(bytes);
    document.getElementById('out').textContent = 'Same bytes read as windows-1252: ' + wrong;
  </script>
</body>
</html>

Best practices

  • Make <meta charset="utf-8"> the first child of <head>, before the <title>, so it lands well inside the first 1024 bytes.
  • Save your files as UTF-8 in your editor. The declaration only describes the bytes, it does not convert them.
  • Send Content-Type: text/html; charset=utf-8 from the server as well, because the HTTP header takes priority over the meta tag.
  • Drop charset from <script> and <link> tags. The HTML Standard lists it as obsolete on both, notes that scripts must already be UTF-8, and says to use an HTTP Content-Type header on a linked resource instead.
  • Leave the declaration out of srcdoc documents, which the HTML Standard says must not have one because their text is already decoded.

Frequently asked questions

Is meta charset utf-8 necessary?
Yes, unless an HTTP header or a byte order mark already declares the encoding. Otherwise the HTML Standard requires meta charset or its http-equiv content-type equivalent, even on pure ASCII pages, and without one browsers may guess a legacy encoding.
Where should the meta charset tag go?
Place the meta charset tag at the top of the head element, before the title. The HTML Standard requires the whole tag to fit within the first 1024 bytes of the document.
What is the difference between meta charset and meta http-equiv content-type?
Meta charset and the http-equiv content-type form are both character encoding declarations with the same effect. A page must not use both, and only meta charset is allowed in XML documents.
Can I use a charset other than UTF-8?
No, the HTML Standard allows only utf-8 as the meta charset value. Legacy encodings such as ISO-8859-1 are non-conforming, and the standard warns that they can have unexpected results on form submission and URL encodings.
Does meta charset override the HTTP Content-Type header?
No, a charset in the HTTP Content-Type header takes priority over meta charset. A byte order mark at the very start of the file outranks both.
Why does my page show characters like é instead of é?
Text like é means UTF-8 bytes are being decoded with a legacy encoding such as windows-1252. Add meta charset utf-8 near the top of the head, save the file as UTF-8 and check the server's Content-Type header.