BYTETOOLS

W3C Nu HTML Checker API

Run the official W3C HTML validator from code and get machine-readable JSON errors with line and column numbers. No key required. Live verified example.

No API key requiredCORS enabledHTTPSFree tier

Endpoint tested and returned HTTP 200 on 2026-08-21

What is the W3C Nu HTML Checker API?

The W3C Nu HTML Checker has a JSON API. `GET https://validator.w3.org/nu/?doc=https://example.com&out=json` validates a live page and returns a `messages` array of errors and warnings. You can also POST an HTML document directly. No API key is required.

This is the same validator behind validator.w3.org, and `out=json` turns it from a web page into a CI-friendly tool. Each message carries a type, a human-readable description and, where the problem maps to a source location, line and column numbers plus an `extract` of the offending markup. That is enough to annotate a pull request diff without any HTML parsing of your own.

Two operational details matter. The checker requires a real `User-Agent`; requests with an empty or missing one are refused, which catches out minimal HTTP clients. And there are two ways in: `?doc=` makes the validator fetch a public URL itself, which cannot work for localhost or staging behind auth, while POSTing the document with `Content-Type: text/html; charset=utf-8` validates markup you supply and is the right choice in CI. W3C also asks heavy users to run their own instance, which is packaged and easy to host.

Quick facts

Base URL
https://validator.w3.org/nu
Authentication
No key. A descriptive User-Agent header is mandatory; requests without one are rejected.
Rate limit
Not published as a number, but W3C throttles automated use and asks high-volume users to self-host the checker, which is available as a jar and a container image.
Pricing
Free and open source.
CORS
Enabled — callable directly from browser JavaScript
Official docs
Read the docs

How to use the W3C Nu HTML Checker API

Every request below was executed against the live API on 2026-08-21, and the response shown is the real body it returned — not an illustration.

1. Validate a live page and return JSON

GET https://validator.w3.org/nu/?doc=https%3A%2F%2Fexample.com&out=json

curl
curl 'https://validator.w3.org/nu/?doc=https%3A%2F%2Fexample.com&out=json'
JavaScript (fetch)
const res = await fetch("https://validator.w3.org/nu/?doc=https%3A%2F%2Fexample.com&out=json");
if (!res.ok) throw new Error(`Request failed: ${res.status}`);
const data = await res.json();
console.log(data);
Python (requests)
import requests

res = requests.get("https://validator.w3.org/nu/?doc=https%3A%2F%2Fexample.com&out=json", timeout=20)
res.raise_for_status()
print(res.json())
Response — HTTP 200
{
  "url": "https://example.com",
  "version": "26.8.20",
  "messages": [
    {
      "type": "error",
      "url": "https://example.com/",
      "message": "The character encoding was not declared. Proceeding using “windows-1252”."
    }
  ]
}

Parameters

ParameterTypeRequiredDescription
docstringOptionalPublic URL for the validator to fetch and check. URL-encode it. https://example.com
outstringRequiredOutput format. Use `json`; the default is HTML intended for browsers. json
(POST body)HTMLOptionalSend the document itself with `Content-Type: text/html; charset=utf-8` to validate markup that is not publicly reachable. <!DOCTYPE html>...
levelstringOptionalSet to `error` to suppress warnings and informational messages. error

Response fields

urlstring
The document that was checked. When you POST a body this is absent or synthetic, so do not rely on it in CI.
versionstring
Checker version, dated like `26.8.20`. Worth logging, because new releases add and refine checks.
messagesarray
The findings. An empty array means the document is valid; there is no separate boolean to check.
messages[].typestring
`error`, `info` or `non-document-error`. A `non-document-error` means the checker itself failed, for example it could not fetch the URL, which is very different from an invalid document.
messages[].subTypestring
Present on some messages, most usefully `warning` on `info` entries and `fatal` on parse-stopping errors.
messages[].messagestring
The human-readable description, using typographic quotes. Do not pattern-match on it; it changes between versions.
messages[].lastLine / firstColumn / lastColumn / extractinteger / string
Source location and a snippet of the offending markup, present when the message maps to a position in the document.

What you can build with the W3C Nu HTML Checker API

  • Fail a CI build when a template produces invalid HTML
  • Annotate pull requests with validation errors at the exact line
  • Audit a whole site for markup errors by validating each URL from a sitemap
  • Check generated HTML from a static site generator or email template builder
  • Teach HTML with authoritative, specific error messages rather than browser guesswork

Common errors and how to fix them

non-document-error in messages

The checker could not retrieve or parse the target, typically a fetch failure or an unreachable URL.

Fix: Distinguish this type from `error`. It means your request failed, not that the HTML is invalid.

403 or connection refused

Missing or empty User-Agent header.

Fix: Always send a descriptive User-Agent that identifies your tool and a contact URL.

Cannot validate localhost

`?doc=` makes W3C's servers fetch the URL, and they cannot reach your machine.

Fix: POST the HTML document in the request body instead, with `Content-Type: text/html; charset=utf-8`.

W3C Nu HTML Checker API — frequently asked questions

Is the W3C HTML validator API free?

Yes, with no key. W3C asks that heavy or automated users run their own instance of the Nu checker, which is distributed as a jar and a container image.

How do I validate HTML that is not publicly accessible?

POST the document as the request body with `Content-Type: text/html; charset=utf-8` and `out=json`. The validator then checks what you sent rather than fetching a URL.

How do I tell whether a document is valid?

An empty `messages` array means valid. There is no boolean field, so count messages, and decide whether `info` entries should count against you.

Why does my HTTP client get rejected?

The checker refuses requests without a User-Agent. Set a descriptive one that names your tool and, ideally, a contact URL.

Tools that pair with this API

W3C Nu HTML Checker is an independent third-party service and is not affiliated with ByteTools or ByteVancer. Details on this page were verified on 2026-08-21; always check the official documentation before relying on this API in production, as terms and limits can change.