Skip to content
Issue docs

No character encoding declared

Importantcharset_declaration_missingIssue 28

What is this issue?

This issue fires when a page declares no character encoding at all — neither <meta charset="…"> nor <meta http-equiv="content-type" content="text/html; charset=…">.

A passing page declares UTF-8 as the first element in <head>:

<head>
  <meta charset="utf-8" />
  …
</head>

This is the "nothing was declared" half of what used to be a single check titled Character encoding missing or not UTF-8. Declaring the wrong encoding is a separate issue, because the fix is different: this one is a missing line, that one is a re-encoding job.

Why it matters

With no declaration, the browser guesses. Modern browsers guess UTF-8 for most documents, but the guess is not guaranteed, it varies by browser and locale, and it can be influenced by the first bytes of the page.

  • A wrong guess is visible damage. Accented and non-Latin characters render as mojibake ("café" as "café"), including in your title and meta description as they appear in search results.
  • The guess happens before your content loads. A browser that starts parsing with the wrong encoding may have to restart, which delays first paint.
  • It costs one line to remove the ambiguity, which is why this is worth reporting even on sites that happen to render correctly today.

How to fix it

  1. Add the declaration as the first element inside <head>:

    <meta charset="utf-8" />

    The spec requires it within the first 1024 bytes of the document, so put it before the title, before any stylesheet, and before any inline script.

  2. Add it in the shared layout rather than page by page, so new templates inherit it.

  3. Send a matching HTTP header too, if you control the server: Content-Type: text/html; charset=utf-8. The header wins over the meta tag, so a mismatched header would override a correct tag.

  4. Verify. Re-scan, and check a page containing non-ASCII characters renders them correctly with the browser's encoding override set to "auto".

Examples

1. No encoding declared

Problem — the <head> names an encoding nowhere, so the browser guesses:

<head>
  <title>Café menu</title>
  <link rel="stylesheet" href="/style.css" />
</head>

Fixed — declared as the first element in <head>:

<head>
  <meta charset="utf-8" />
  <title>Café menu</title>
  <link rel="stylesheet" href="/style.css" />
</head>

2. The http-equiv form also passes

This declaration is older and more verbose, but it declares an encoding, so it does not raise this issue.

Passes:

<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>Café menu</title>
</head>

Preferred — the short form is what the HTML standard recommends:

<head>
  <meta charset="utf-8" />
  <title>Café menu</title>
</head>

3. A <head> that only looks like it declares one

Problem — the attribute is content, not charset, so nothing is declared and the issue fires:

<head>
  <meta name="charset" content="utf-8" />
  <title>Café menu</title>
</head>

Fixed:

<head>
  <meta charset="utf-8" />
  <title>Café menu</title>
</head>

How PixyScan detects this

  1. HTML parsing. The crawler reads the <head> of the fetched document.

  2. Two accepted forms. It reads whichever is present:

    • the charset attribute of <meta charset="…">
    • the charset= parameter of <meta http-equiv="content-type" content="…">
  3. Pass/fail.

    • Fails when neither form yields a value — including a page with no <head> at all.
    • Passes when either yields a value. Whether that value is UTF-8 is the separate check, charset_declaration_not_utf8.

The two conditions are mutually exclusive, so a page never raises both.

What we store

Storage Level

Page Level — evaluated for each crawled URL.


Database Table / Prisma Model

PageHtmlHeadAudit

One row per crawled URL, keyed by urlId.


Fields Used

Field Type Description
charsetValue String? The character encoding the page declares. null is exactly the state this issue reports — nothing was declared

The same column is read by charset_declaration_not_utf8 (#29), which judges the value when there is one. null raises this issue; a non-null value raises the other or neither, so the two are mutually exclusive and a page never appears under both.


Detection Dependencies

  • HTML Document — the <head> of the fetched page is parsed for <meta charset> and <meta http-equiv="content-type">

Further reading