/ โ† llms.txt Fixes / llms.txt Format Errors
In this guide
  1. How a program reads llms.txt
  2. The format errors, what the parser sees, and the fix
  3. Format errors that are really serving problems
  4. A broken file and the same file corrected
  5. The fix, step by step
  6. A small checker you can run before uploading
  7. Edge cases that confuse people
  8. Keeping the format right after the fix
  9. Questions and answers

How a program reads llms.txt

The llms.txt proposal, published by Jeremy Howard of Answer.AI in September 2024, is deliberately small. Instead of inventing a new syntax it picks a handful of ordinary Markdown elements and gives each one a job. A tool that reads the file does not render the Markdown the way a browser or a README viewer would. It walks through the lines and asks a few simple questions: where is the H1, is there a blockquote straight after it, where does each H2 begin, and which lines inside those H2 blocks are list items holding a link.

That approach is forgiving about style and strict about structure. Extra blank lines, long notes or unusual section names cause no trouble. A second H1, a heading in the wrong place or a link written as a naked address can change how the whole file is split up, and the tool then either skips content silently or fails to read it at all.

The parts, in the order a parser expects them

PartMarkdown usedRequired?What the parser does with it
NameOne line starting # Yes, the only required partTakes the text as the title of the site or project
SummaryLines starting > directly under the H1No, but expectedTreats it as the short description of the whole site
DetailsParagraphs or lists, no headingsNoKeeps it as free text that belongs to the header
SectionsLines starting ## No, but that is where links liveStarts a new named group of links
Entries- [Name](URL): noteInside sectionsSplits each item into a title, an address and a description
OptionalA section headed ## OptionalNoMarks links a tool may drop when it is short of space

The proposal site also publishes a small open source Python library and command-line tool that parse the file in exactly this way and can expand it into a single context document. If your file reads cleanly with a strict parser like that, it will read cleanly with looser ones.

๐Ÿ’ก The proposal is still only a proposal. As far as we know, no major AI search provider has confirmed that it reads llms.txt. Fixing the format matters for the tools that do read it, such as coding assistants and documentation tools, and it is what the auditor validates against.

The format errors, what the parser sees, and the fix

These are the faults that turn up again and again in real files. Most come from writing the file in a word processor or CMS editor, or from pasting in a sitemap and adding a heading on top.

What is in the fileWhat the parser seesFix
No line starting # , or the name written as #Site with no spaceNo title. Many Markdown readers need the space after the hash.Make the first line # Your Site Name with a single space.
Two or more H1 lines, often one per sectionOnly one of them can be the name; the others break the header, and some tools stop at the second.Keep one H1 at the top. Turn the rest into ## sections.
The name underlined with ==== (setext style)Some simple line-based parsers only look for the hash form.Use the # form.
Summary written as a normal paragraphNo summary; the text lands in the free details block.Start each summary line with > .
Summary placed below the first sectionIt belongs to that section, not to the site.Move it to the line after the H1.
### or ## headings in the details area before the link sectionsThe details area is meant to have no headings, so the parser starts a section early.Turn those headings into bold text or plain sentences, or make them proper link sections.
Links outside any H2 sectionFree text, not an entry. The link is never listed.Put every link list under a ## heading.
Bare URLs such as - https://www.example.co.uk/delivery/No name and no note, or no entry at all.Write - [Delivery](https://www.example.co.uk/delivery/): areas, costs, times.
Note joined with a dash or brackets instead of a colonThe whole tail may be kept as part of the name, or thrown away.Use a colon and a space after the closing bracket.
Relative links such as /pricing/A tool reading the file on its own has no base address to resolve against.Use full https:// addresses on your canonical host.
Bullets typed as โ€ข, or numbered 1. itemsBullets are not Markdown list markers; numbered lists are accepted by some parsers and not others.Use - at the start of every entry.
Nested lists or tables inside a sectionUnpredictable. Sub-items may be merged into the parent note or dropped.One flat list per section. Split a big group into two sections.

Why the colon matters

The proposal describes each entry as a required Markdown link, then optionally a colon and notes about the linked page. Parsers split on exactly that pattern. - [Returns](https://www.example.co.uk/returns/) - 30 days, free labels contains a perfectly good link, but the text after it is not attached as a note by a strict parser. Change the dash to a colon and it is.

Links whose address contains brackets

A URL that contains a closing round bracket, common on wiki-style sites, ends the Markdown link early. Replace ( and ) in the address with %28 and %29. Square brackets inside the link name have the same effect on the name; take them out or rephrase.

Format errors that are really serving problems

Sometimes the text you uploaded is correct, but what reaches the tool is not. The auditor fetches the file over HTTP, so it sees what your server sends, not what is on your disk. Check these before you edit a single line.

curl -sS -D - https://www.example.co.uk/llms.txt -o llms-check.txt
head -c 3 llms-check.txt | xxd
file llms-check.txt

The response headers show the status and content type. If xxd prints efbb bf, the file starts with a byte order mark. If file reports HTML or an encoding other than UTF-8 or ASCII, fix that first.

A broken file and the same file corrected

This is the kind of file the auditor flags. It was typed into a website builder by the owner of a fictional garden centre, then partly pasted from a sitemap.

Brambleford Garden Centre
=========================

Welcome to Brambleford! We are the best garden centre in the county.

# Plants
โ€ข https://www.example.co.uk/plants/perennials
โ€ข https://www.example.co.uk/plants/shrubs

# Visiting us
### Opening times
[Opening hours](/visit/hours) - seasonal changes
1. [Cafe](https://www.example.co.uk/cafe/) (menu, allergens)

Counting the problems: a setext title, no blockquote, a marketing sentence as the only description, three H1 lines, typographic bullets with bare URLs, an H3 inside the link area, a relative link, a dash instead of a colon and a numbered item with its note in brackets. Here is the same content in the proposed structure:

# Brambleford Garden Centre

> Independent garden centre near Chesterfield selling plants, garden
> supplies and houseplants, with an on-site cafe. We do not sell online.

Prices include VAT. Plant stock changes weekly, so pages describe ranges
rather than individual plants.

## Plants
- [Perennials](https://www.example.co.uk/plants/perennials/): hardy border plants, when each range is in stock
- [Shrubs](https://www.example.co.uk/plants/shrubs/): evergreen and flowering shrubs, pot sizes, planting advice

## Visiting us
- [Opening hours](https://www.example.co.uk/visit/hours/): seasonal hours, bank holidays, late opening
- [Cafe](https://www.example.co.uk/cafe/): menu, allergen information, when food service stops

Nothing about the business changed. The file now has one title, a summary a parser can pick out, a free-text line of facts, and two sections whose every line is a complete entry.

The fix, step by step

Step 1

Fetch the file exactly as a tool sees it

Do not start from the copy on your computer. Run curl -sS -D - https://www.example.co.uk/llms.txt against your real domain and read what comes back: the status line, the Content-Type header and the first few lines of the body. If the body begins with an HTML doctype, a cookie banner or theme markup, the problem is how the file is served, and editing the Markdown will not help until that is fixed.

Step 2

Strip anything that is not Markdown

Open the source file in a plain text editor, never a word processor. Remove HTML tags, tables, images, typographic bullets, emoji used as markers and any tracking code a CMS added. Replace curly quotes and long dashes pasted from documents only where they sit inside URLs. Save the result as UTF-8 without a byte order mark, with the file name llms.txt in lower case, and keep that plain file as your master copy.

Step 3

Make the first line the only H1

The very first line of the file should be a hash, one space and the name of your site or business, for example # Brambleford Garden Centre. Delete any greeting or blank text above it. Search the rest of the file for lines that begin with a single hash and change each one into an H2 section heading with two hashes, or remove it if it only repeated the name. One title per file is the rule parsers depend on.

Step 4

Put the summary in one blockquote

Directly under the H1, after one blank line, write two or three sentences that say what the site is, who it serves and anything a reader must know to interpret the rest, such as the country, currency or whether you sell online. Start every line of that summary with > and a space. Keep it factual. Any further background goes in plain paragraphs below the blockquote, without headings of any level.

Step 5

Move every link into an H2 section

Group your links into a few sections that describe what the pages are for, such as ## Services, ## Help or ## Policies, each introduced by two hashes and a space. Every link in the file must sit in a list under one of those headings. Remove any H3 or deeper headings inside sections and split a crowded group into two sections instead. Put nice-to-have pages last under ## Optional.

Step 6

Rewrite each entry as a link with a note

Each line in a section should read - [Page name](https://full-address/): short note. Use a hyphen and a space to start the line, square brackets round a readable page name, the full canonical address in round brackets, then a colon and a note of a few words saying what the page contains. Convert bare URLs, numbered items, relative paths and notes attached with dashes or brackets into that one pattern.

Step 7

Run the checker and the auditor again

Run the checker script from this guide against the local file, fix anything it reports, then upload the file to the site root, replacing the old copy. Clear any page cache or CDN cache that might keep serving the previous version. Fetch it once more with curl to confirm the live body matches your master copy, then run the llms.txt Auditor on the domain and confirm the format finding has gone.

A small checker you can run before uploading

This script needs nothing beyond Python 3. It reads a local file or a live URL and prints every structural problem it finds, using the same rules as the table above. It does not check that the links work; that is a separate job covered in the broken links guide.

import re, sys, urllib.request

src = sys.argv[1]
if src.startswith('http'):
    with urllib.request.urlopen(src) as r:
        ctype, raw = r.headers.get('Content-Type', ''), r.read()
    if 'html' in ctype:
        print('served as', ctype)
else:
    raw = open(src, 'rb').read()

if raw.startswith(b'\xef\xbb\xbf'):
    print('starts with a byte order mark')
text = raw.decode('utf-8', errors='replace')
if '๏ฟฝ' in text:
    print('contains bytes that are not UTF-8')

lines = text.splitlines()
first = next((l for l in lines if l.strip()), '')
if not first.startswith('# '):
    print('first line is not an H1:', first[:60])
h1 = [l for l in lines if re.match(r'#\s', l)]
if len(h1) != 1:
    print('expected 1 H1, found', len(h1))

section = None
entry = re.compile(r'^- \[[^\]]+\]\(https?://[^)\s]+\)(: .+)?$')
for n, l in enumerate(lines, 1):
    if l.startswith('## '):
        section = l[3:]
    elif l.startswith('#'):
        if not l.startswith('# '):
            print(n, 'heading not allowed here:', l[:60])
    elif section and l.strip() and not entry.match(l.strip()):
        print(n, 'not a valid entry:', l[:70])
    elif section is None and re.search(r'\]\(|https?://', l):
        print(n, 'link outside any section')
print('done')

Save it as llmscheck.py and run python3 llmscheck.py llms.txt or python3 llmscheck.py https://www.example.co.uk/llms.txt. A clean file prints only done. The note is optional in the entry pattern, because the proposal makes it optional, so an entry without one passes this check. The auditor treats missing notes as a content weakness rather than a format error, so fill them in anyway.

Edge cases that confuse people

Linking to Markdown versions of pages

The proposal also suggests that sites offer a clean Markdown copy of useful pages at the same address with .md added. If you do that, the entries in llms.txt can point at those copies. It does not change the format of llms.txt itself, and if you have not built the copies, link to the normal HTML pages rather than to addresses that return errors.

Very long notes

A note can run to more than one sentence, but it must stay on the same line as the link. A line break in the middle of a note ends the entry, and the continuation line is then read as a stray line inside the section. If you need more than a sentence or two, the detail belongs on the linked page.

Section names

Apart from Optional, the proposal does not fix section names, so ## Docs, ## Services and ## Policies are all fine. Avoid naming a normal section Optional by accident, for example ## Optional extras on a shop, because some tools may treat everything under a heading starting with that word as skippable. Call it ## Add-on products instead.

Comments and front matter

Static site generators sometimes leave YAML front matter between --- lines at the top of a Markdown file, and developers sometimes leave HTML comments. Both push the H1 off the first line. Strip them from the published output.

Line endings and trailing spaces

Windows line endings and trailing spaces are harmless to the parsers we know of. You do not need to convert them, although many editors will tidy them automatically.

Keeping the format right after the fix

Once the structure is sound, the next thing the auditor looks at is whether the notes are any use. That is a different problem, covered in the thin content guide.

Questions and answers

1. Is there an official llms.txt validator?

There is no validator run by a standards body, because llms.txt is a proposal rather than a formal standard. The proposal site publishes an open source Python library and command-line tool that parse the file, which is a good strict test. Our llms.txt Auditor validates the file against the proposed format when it fetches it, and the checker script in this guide catches the common structural errors locally before you upload anything to the server.

2. Can llms.txt have more than one H1?

No. The proposal describes a single H1 containing the name of the site or project, and it is the one required element. A second H1 leaves a parser unsure which line is the name, and simple line-based tools may treat the second one as the start of something else entirely. If your file has one H1 per topic, keep the first as the site name and change the others into H2 section headings holding lists of links.

3. Do I have to include the blockquote summary?

Only the H1 is strictly required, so a file without a blockquote is not invalid. In practice the summary is the most useful part for a tool that reads the file, because it is the one place that describes the whole site in a sentence or two. The auditor expects to find it. If you already have a summary written as a normal paragraph, simply start each of its lines with a greater-than sign and a space.

4. Can I use H3 headings inside a section?

The proposal defines H2 sections containing lists of links, and does not define deeper headings. Some tools will cope with an H3, but others will treat it as unexpected text or split the section in the wrong place. The safer course is to keep each H2 as one flat list, and if a section has grown large enough to need subheadings, split it into two or more H2 sections with clear names of their own.

5. Should links in llms.txt be absolute or relative?

Use absolute addresses starting with https and your canonical host name. A tool may download llms.txt on its own, pass it to a model or store it, and at that point there is no page address to resolve a relative link against. Absolute links also make it obvious which host is canonical, which avoids a tool following links to the non-www version or an old domain that only redirects back to the real site.

6. What content type should llms.txt be served with?

Serve it as text/plain or text/markdown with charset=utf-8. Either works for the tools we know of, and text/plain has the advantage that browsers display it rather than offering a download. What causes trouble is text/html, which usually means a CMS or app server is answering with a page instead of the file, or a binary type, which some tools refuse to treat as text. Check the header with curl after every server change.

7. Will fixing the format improve my rankings or AI citations?

There is no evidence that it will. As far as we know, none of the major search or AI answer providers has confirmed reading llms.txt when ranking pages or choosing sources to cite. A correctly formatted file simply means that the tools which do read it, mostly developer and research tools, can understand it. That is worth an hour of work, but it is not a substitute for crawlable, clearly written pages on the site itself.

Check your llms.txt structure

The llms.txt Auditor fetches your /llms.txt and /llms-full.txt files, validates them against the proposed format, checks that each linked URL responds, confirms robots.txt allows the relevant AI crawlers and scores the quality of the content.

Open llms.txt Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All llms.txt Fixes  ·  llms.txt Guide  ·  Fixing a Missing llms.txt  ·  Fixing Thin llms.txt Content  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.