Table of Contents
- 1. What Is llms.txt?
- 2. Why You Need It -- How It Differs from robots.txt
- 3. Format Specification -- What to Write and How
- 4. What Information to Include -- Required, Recommended, and Optional
- 5. llms.txt vs llms-full.txt
- 6. Static File vs Dynamic Generation -- Which Should You Choose?
- 7. Implementation -- Code Examples by Framework
- 8. Post-Setup Verification and Testing
- 9. Measured: Do AI Crawlers Actually Fetch llms.txt?
- 10. Real-World llms.txt Examples
- FAQ
The age of AI search is here. ChatGPT web search, Perplexity, Google AI Overviews -- as more users get information through AI, making sure AI understands your site correctly has become critically important.
That is where llms.txt comes in. If robots.txt tells crawlers "you may / may not crawl this page," llms.txt is a signpost that tells AI "here is what this site covers, and here is where to read the details." There is, however, no evidence that publishing one gets you cited in AI answers, and in this site's own access logs no AI crawler fetched it even once over three and a half days. This guide covers what kind of site it is actually worth adding to.
This article covers everything: the llms.txt format specification, what information to include, the criteria for choosing between static and dynamic generation, and implementation code for major frameworks.
1. What Is llms.txt?
llms.txt is a plain text file (in Markdown format) placed in the root directory of your website, designed to communicate your site's overview, structure, and content catalog to LLMs (Large Language Models).
Basic Information
| Item | Details |
|---|---|
| File Name | llms.txt |
| Location | Domain root (https://example.com/llms.txt). Since v2 it can also sit in a subpath (/docs/llms.txt), covering the pages under it |
| Format | Markdown (plain text) |
| Encoding | UTF-8 |
| Proposed By | llmstxt.org (Jeremy Howard et al.) |
| Standardization | De facto standard (not a formal RFC or specification). Current version: v2 (revised August 2026) |
| Main Readers | AI agents that need information while helping a user (the spec's intended use, especially coding agents navigating documentation). No vendor has officially stated that training or search crawlers such as GPTBot read it |
In One Sentence
robots.txt = "Keep out" / llms.txt = "Here's what our site is about"
While robots.txt is an access control file (allow/deny), llms.txt is a content description file (self-introduction). The two don't conflict -- they're actually meant to be used together.
2. Why You Need It -- How It Differs from robots.txt
You might think, "Can't AI understand my site from sitemaps and meta tags?" That's true to an extent, but llms.txt offers distinct advantages.
Comparing robots.txt / sitemap.xml / llms.txt
| File | Purpose | Target | Content |
|---|---|---|---|
| robots.txt | Allow/deny crawling | All crawlers | Allow/Disallow rules |
| sitemap.xml | Provide page list | Search engines | URLs, update dates, priority |
| llms.txt | Describe site content | LLM crawlers | Overview, structure, content summaries |
Three Reasons You Need llms.txt
Reason 1: LLMs Can't Efficiently Crawl an Entire Site
While Googlebot crawls billions of pages to build a massive index, LLM crawlers don't cover sites as comprehensively. By placing an llms.txt file, you can efficiently tell AI, "Here's the most important content on this site."
Reason 2: It gets you cited in AI answers -- a common claim with no evidence behind it
You will often read that llms.txt makes ChatGPT or Perplexity more likely to cite your site, but there is no data or official vendor statement showing that. Google explicitly says you do not need AI text files to appear in AI Overviews or AI Mode (Google Search Central). It is more accurate to treat llms.txt as a table of contents that helps agents reach the right information quickly than as a way to earn citations; Section 9 checks this against real logs.
For a detailed explanation of LLMO, see "What Is LLMO?"
Reason 3: It Conveys Meta Information That sitemap.xml Can't
sitemap.xml is just a list of URLs. With llms.txt, you can also communicate:
- Your site's theme and areas of expertise
- Summaries and categories for each piece of content
- Your site's update frequency and scale
- Whether you offer multilingual support
- Contact information
3. Format Specification -- What to Write and How
llms.txt Format Structure
H1 site name → blockquote summary → H2 section group
llms.txt is written in Markdown format. Here's the format based on the llmstxt.org specification.
Basic Structure
# Site Name
> A brief description of the site. 1-3 sentences covering the site's theme, audience, and value proposition.
## Section Name 1
- [Page Title](URL): Brief summary of the page
## Section Name 2
- [Page Title](URL): Brief summary of the page
- [Page Title](URL): Brief summary of the page
Format Rules
| Element | Markdown Syntax | Purpose |
|---|---|---|
| H1 Heading | # Site Name | The site's official name. Only one per file |
| Blockquote | > Overview text | Site description. Placed right after H1 |
| H2 Heading | ## Section Name | Content grouping |
| List Link | - [Title](URL): Description | Individual content information |
Practical Example
# My Tech Blog
> My Tech Blog is a software engineering blog covering web development, cloud infrastructure, and AI tools. Updated weekly with practical tutorials and comparisons.
## Main Sections
- [Articles](https://example.com/articles): 50+ in-depth technical articles
- [Tutorials](https://example.com/tutorials): Step-by-step coding tutorials
## Popular Articles
- [React vs Vue in 2026](https://example.com/articles/react-vs-vue): A detailed comparison of React and Vue.js for modern web development, covering performance, ecosystem, and learning curve.
- [Docker for Beginners](https://example.com/articles/docker-beginners): Complete guide to Docker containers for developers who have never used containerization.
## Site Information
- URL: https://example.com
- Sitemap: https://example.com/sitemap.xml
- Languages: en, ja
- Contact: admin@example.com
Important Notes
- Write in English by default. The llms.txt specification and examples are all in English, making it the best practice. For multilingual sites, write in English and specify supported languages with
Languages: ja, en, es, .... However, for single-language sites (e.g., a site entirely in French, entirely in Russian, etc.), writing in the site's language is perfectly acceptable. Major LLMs (GPT, Claude, Gemini, etc.) process most languages with high accuracy, and users of such sites will query in the same language, ensuring consistent responses - Always use UTF-8 encoding. Other encodings like Shift-JIS may cause character corruption
- Use absolute URLs (complete URLs starting with https://)
- Only one H1 per file. Use H2 for section divisions
4. What Information to Include -- Required, Recommended, and Optional
Many people get stuck deciding what to write, so here's a breakdown by priority.
Note that the specification (llmstxt.org) requires only the H1 with the site name; the summary blockquote and the H2 link lists are formally optional. "Required" below means the minimum this guide considers necessary for the file to be worth having.
Required Information (Without These, llms.txt Serves No Purpose)
| Information | Where to Write It | Example |
|---|---|---|
| Site Name | H1 heading | # AI Arte |
| Site Overview | Blockquote | > AI learning platform... |
| Main Sections | H2 + link list | - [Articles](URL): Description |
Recommended Information (Improves AI Understanding)
| Information | Why It Matters |
|---|---|
| Full Content List | Lets AI grasp the full scope of your site |
| One-Line Summary per Content | Gives AI a preview of each page's content |
| Category/Tag Structure | Shows the site's information architecture |
| Site URL | Declares the canonical URL |
| Sitemap URL | Points to the detailed URL list |
| Supported Languages | Important for multilingual sites |
| Contact Info | Establishes the site operator's identity |
Optional Information (Nice to Have, but Not Essential)
- Tech Stack: What the site is built with (frameworks, etc.)
- Update Frequency: How often new content is added
- Total Content Count: Number of articles, etc.
- License/Citation Policy: Whether AI is allowed to cite your content
- API Information: If programmatic access is available
Information You Should NOT Include
- Sensitive Information: Admin panel URLs, internal API endpoints, etc.
- Personal Information: Unnecessarily detailed personal data (addresses, phone numbers, etc.)
- Credentials: API keys, passwords, etc.
5. llms.txt vs llms-full.txt
llms-full.txt puts a site's entire content into a single file. It is not part of the llmstxt.org specification; it is a convention that spread because documentation platforms such as Mintlify generate it automatically alongside llms.txt (Mintlify docs). Specification v2 instead recommends providing a Markdown version of each page (page.md or page.html.md) and linking to those from llms.txt, rather than bundling everything into one file.
| File | Content | Size Estimate | Purpose |
|---|---|---|---|
| llms.txt | Site overview, structure, link list | 1-50KB | A "table of contents" for the entire site |
| llms-full.txt | Full text of all content | 100KB - several MB | Providing full content text to AI |
When You Need llms-full.txt
- Technical Documentation: API references and library docs where providing the full text to AI improves answer accuracy
- Knowledge Bases: FAQ collections and glossaries -- content that's frequently cited in fragments
When You Don't Need llms-full.txt
- Blogs and Media Sites: With many articles, combining everything into one file would be too large. The summaries in llms.txt are sufficient
- E-commerce Sites: Product information is better served through structured data (JSON-LD, etc.)
- Corporate Sites: With few pages, llms.txt alone covers everything
For most blogs and media sites, llms.txt alone is enough. Think of llms-full.txt as something designed for technical documentation.
6. Static File vs Dynamic Generation -- Which Should You Choose?
Static File vs Dynamic Generation — which to choose
Trade-off: implementation effort vs ongoing updates
There are two main approaches to maintaining llms.txt.
Approach 1: Static File
Place a text file directly at public/llms.txt (or an equivalent path).
Pros:
- Simplest implementation (just drop the file in)
- Zero server load
- Works without any framework
Cons:
- Every time you add or update content, you need to manually update the file
- Forgetting to update means stale information is served to AI
- Content counts and categories can drift from reality
Approach 2: Dynamic Generation
The application intercepts requests to /llms.txt, fetches the latest data from the database, and dynamically generates the text.
Pros:
- Always reflects the latest information
- Adding an article automatically updates llms.txt
- Content counts and category names are always accurate
Cons:
- Requires more implementation effort (route definition + controller)
- Each request triggers a database query (mitigated with caching)
- Requires a framework
Decision Criteria
| Condition | Recommendation |
|---|---|
| 10 or fewer content items, rarely updated | Static file is fine |
| 10+ content items or updated monthly or more | Dynamic generation recommended |
| Using WordPress / Laravel / Django, etc. | Dynamic generation is easy to implement |
| Static site (Hugo, Jekyll, Astro, etc.) | Auto-generation at build time is ideal |
| Solo operation, want minimal maintenance | Dynamic generation (set it up once and forget it) |
Bottom line: when in doubt, go dynamic. The initial implementation cost is higher, but since you can "set it and forget it," long-term maintenance costs are lower. The worst-case scenario is using a static file and forgetting to update it, leaving AI with outdated information.
7. Implementation -- Code Examples by Framework
Let's look at how to implement dynamic llms.txt generation in major frameworks.
Laravel (PHP)
Route Definition (routes/web.php):
use App\Http\Controllers\LlmsTxtController;
Route::get('/llms.txt', [LlmsTxtController::class, 'index']);
Controller (app/Http/Controllers/LlmsTxtController.php):
class LlmsTxtController extends Controller
{
public function index()
{
$articles = Article::published()
->with(['translations' => fn($q) => $q->where('locale', 'en')])
->orderBy('published_at')
->get();
$lines = [];
$lines[] = '# My Site Name';
$lines[] = '';
$lines[] = '> Site description here.';
$lines[] = '';
$lines[] = '## All Articles (' . $articles->count() . ')';
$lines[] = '';
foreach ($articles as $article) {
$t = $article->translations->first();
if (!$t) continue;
$url = 'https://example.com/en/articles/' . $article->slug;
$lines[] = '- [' . $t->title . '](' . $url . '): ' . $t->meta_description;
}
$content = implode("\n", $lines);
return response($content, 200)
->header('Content-Type', 'text/plain; charset=utf-8');
}
}
The key point is to explicitly set Content-Type: text/plain; charset=utf-8. Without it, the response might be interpreted as HTML.
Django (Python)
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path('llms.txt', views.llms_txt, name='llms_txt'),
]
# views.py
from django.http import HttpResponse
from .models import Article
def llms_txt(request):
articles = Article.objects.filter(
status='published'
).order_by('published_at')
lines = ['# My Site', '', '> Description.', '', '## Articles', '']
for a in articles:
lines.append(f'- [{a.title}](https://example.com/articles/{a.slug}): {a.meta_description}')
content = '\n'.join(lines)
return HttpResponse(content, content_type='text/plain; charset=utf-8')
Next.js (TypeScript)
// app/llms.txt/route.ts (App Router)
import { NextResponse } from 'next/server'
export async function GET() {
// Fetch data from DB or CMS
const posts = await getAllPosts()
const lines = [
'# My Site',
'',
'> Description.',
'',
'## Articles',
'',
...posts.map(p =>
`- [${p.title}](https://example.com/posts/${p.slug}): ${p.description}`
),
]
return new NextResponse(lines.join('\n'), {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
})
}
WordPress (PHP)
Add to functions.php or as a plugin:
// functions.php
add_action('init', function() {
add_rewrite_rule('^llms\.txt$', 'index.php?llms_txt=1', 'top');
});
add_filter('query_vars', function($vars) {
$vars[] = 'llms_txt';
return $vars;
});
add_action('template_redirect', function() {
if (!get_query_var('llms_txt')) return;
header('Content-Type: text/plain; charset=utf-8');
$posts = get_posts(['numberposts' => -1, 'post_status' => 'publish']);
echo "# " . get_bloginfo('name') . "\n\n";
echo "> " . get_bloginfo('description') . "\n\n";
echo "## Articles (" . count($posts) . ")\n\n";
foreach ($posts as $post) {
$url = get_permalink($post);
$desc = get_the_excerpt($post);
echo "- [{$post->post_title}]({$url}): {$desc}\n";
}
exit;
});
For WordPress, don't forget to re-save your permalink settings (flush rewrite rules) after adding the code.
Static Site Generators (Hugo / Astro, etc.)
Write a script to auto-generate it at build time.
# build-llms-txt.sh (example for Hugo)
#!/bin/bash
echo "# My Site" > public/llms.txt
echo "" >> public/llms.txt
echo "> Site description." >> public/llms.txt
echo "" >> public/llms.txt
echo "## Articles" >> public/llms.txt
echo "" >> public/llms.txt
for file in content/posts/*.md; do
title=$(grep '^title:' "$file" | sed 's/title: //')
slug=$(basename "$file" .md)
desc=$(grep '^description:' "$file" | sed 's/description: //')
echo "- [${title}](https://example.com/posts/${slug}): ${desc}" >> public/llms.txt
done
Run this before builds in your CI pipeline (GitHub Actions, etc.) and it will auto-update with every deployment.
8. Post-Setup Verification and Testing
After setting up llms.txt, verify the following.
Basic Checklist
| Check Item | How to Verify |
|---|---|
| Accessible via URL | curl https://yoursite.com/llms.txt |
| Correct Content-Type | Use curl -I to confirm text/plain; charset=utf-8 |
| No character encoding issues | Open it directly in a browser and check for correct display |
| Links are valid | Confirm all listed URLs are actually accessible |
| HTTP status is 200 | curl -o /dev/null -w "%{http_code}" |
| Not blocked by robots.txt | Ensure robots.txt doesn't contain Disallow: /llms.txt |
Additional Checks for Dynamic Generation
- Check llms.txt after adding a new article: Is the new article reflected?
- Content count is correct: Does "All Articles (27)" match the actual number of published articles?
- Unpublished articles are excluded: Confirm that drafts and scheduled posts don't appear
Validation Tools
There is no official validator for the llms.txt format (as of September 29, 2026). Chrome's Lighthouse has an llms.txt item among its "agentic browsing" audits, but it only checks whether fetching the file returns a server error; if the file does not exist (404), the audit is marked not applicable (Chrome for Developers). Check the contents with the methods below.
- Have ChatGPT or Claude read it: Ask "Read https://yoursite.com/llms.txt and tell me about this site"
- Markdown previewer: Paste the llms.txt content into a Markdown previewer to check that the structure renders correctly
- SEO audit tools: Some SEO audit tools have begun supporting llms.txt presence checks
9. Measured: Do AI Crawlers Actually Fetch llms.txt?
People often say "publish it and AI will read it," but whether anything actually fetches it is something you can check in your own server's access logs. This site (arte.itlibra.com) serves a dynamically generated /llms.txt, so we counted requests by User-Agent from September 26, 07:20 to September 29, 12:54 UTC (about three and a half days, 86,696 requests in total).
| Crawler (User-Agent) | All requests in the period | robots.txt | llms.txt |
|---|---|---|---|
| OAI-SearchBot (OpenAI search) | 866 | 20 | 0 |
| ChatGPT-User (ChatGPT opening a page for a user) | 1,275 | 2 | 0 |
| ClaudeBot (Anthropic) | 502 | 29 | 0 |
| Claude-User (Claude opening a page for a user) | 438 | 70 | 0 |
| PerplexityBot | 1,086 | 19 | 0 |
| Googlebot | 2,186 | 14 | 0 |
| bingbot | 4,362 | 21 | 0 |
/llms.txt was requested only three times in that period: twice from the command line (curl) and once by a site-audit tool. AI crawlers read articles hundreds of times but never opened llms.txt. Many of them did check robots.txt, so it is not that they skip small files; they simply do not look for llms.txt.
This is three and a half days of logs from one site, and other sites or longer periods may look different. Combined with the official statements, though, the picture is clear.
- Google: states that "You don't need to create new machine readable files, AI text files, or markup" to appear in AI Overviews or AI Mode (AI features and your website)
- The specification (v2, August 2026): expects llms.txt to be used at inference time, when an agent needs information while helping a user, rather than for training, and says it is used most heavily by coding agents navigating software documentation (llmstxt.org)
- Chrome Lighthouse: its "agentic browsing" audits include llms.txt, but a page fails only if fetching the file returns a server error. A missing file (404) is marked not applicable and costs nothing (Chrome for Developers)
Deciding Whether to Add One
| Type of site | Verdict | Why |
|---|---|---|
| API or library documentation | Add it (plus Markdown versions of each page) | Coding agents really do follow it; this is the main use the specification has in mind |
| Blog or media site | Harmless to add, but do not expect more traffic or citations | In this site's logs, AI crawlers read the articles directly. What matters first is the quality of the articles and not blocking AI crawlers in robots.txt |
| Small corporate site | No rush | With few pages, the homepage and sitemap are enough |
If you do add one, your own logs are the reliable way to see whether it is used. For access logs in the standard nginx or Apache format (combined), this one line counts the User-Agents that requested /llms.txt, most frequent first.
grep ' /llms.txt ' access.log | awk -F'"' '{print $6}' | sort | uniq -c | sort -rn
10. Real-World llms.txt Examples
OpenAI, Anthropic and Google (Gemini API) publish llms.txt files for their own developer documentation (listed on the specification page). We found no statistics on adoption rates, so treat the table below as a rough indication of trends.
Types of Sites Leading Adoption
| Site Type | Adoption Rate | Reason |
|---|---|---|
| AI-Related Services and Tools | High | The AI industry itself is highly LLMO-conscious |
| Technical Documentation | High | Strong demand for AI to accurately understand their content |
| Tech Blogs | Moderate | High sensitivity to technical trends |
| Corporate Sites | Low | Awareness is still limited |
| E-commerce Sites | Low | Structured data (JSON-LD) is the priority |
What Makes a Good llms.txt
- Clear, concise overview -- the site's area of expertise is immediately apparent
- All content listed with summaries -- AI can grasp the full picture
- Category structure is explicit -- the information architecture is clear
- Dynamically generated -- always reflects the latest state
What Makes a Bad llms.txt
- Only site name and contact info -- too little information to help AI understand anything meaningful
- Full content text copied in -- llms.txt is a "table of contents," not a "full text." Full text belongs in llms-full.txt
- Left outdated -- claiming "10 articles" when there are actually 50 undermines credibility
- Contains sensitive information -- admin panel URLs or API keys exposed
FAQ
Q. Will my site not appear in AI search results without llms.txt?
No. AI systems can read your pages directly and cite them without llms.txt. Google explicitly says no AI text files are needed to appear in AI Overviews or AI Mode, and in this site's logs AI crawlers read articles hundreds of times but never opened llms.txt. It is not something you lose out by skipping; it is an optional file for when you want to guide agents.
Q. Does llms.txt matter if I'm blocking AI crawlers in robots.txt?
If you're blocking bots like User-agent: GPTBot with Disallow in robots.txt, those bots won't crawl your site. However, llms.txt operates independently of robots.txt rules. AI might still access llms.txt through other means (such as a user directly pasting the URL). If you're intentionally blocking AI crawlers, not placing an llms.txt file is the consistent approach.
Q. What language should llms.txt be written in?
For multilingual sites, English. For single-language sites, the site's language is also fine. The specification and examples are predominantly in English, making it the most logical choice for multilingual sites as a neutral language. However, if a site's content is entirely in one language, writing llms.txt in that language is acceptable. Major LLMs process most languages with high accuracy, and users will query in the same language as the site, resulting in consistent responses.
Q. Is there a file size limit for llms.txt?
The specification sets no limit; it only says the file should stay small enough to fit in context. For reference, this site's llms.txt lists 225 articles and 40 course chapters, one line each, and comes to about 116 KB (as of September 29, 2026). If yours grows large, shorten the one-line summaries, move secondary links to ## Optional, or split it into separate llms.txt files per subpath as v2 allows. To provide full text, link to Markdown versions of individual pages.
Q. How often should I update it?
With dynamic generation, you don't need to worry -- the latest information is returned with every request. For static files, updating whenever you add or modify content is ideal. At minimum, review and update monthly. If stale information is likely to linger, switching to dynamic generation is recommended.
Q. Does it affect SEO?
It does not affect Google rankings. Google says that, including for AI Overviews and AI Mode, no AI text files or special markup are needed and the usual SEO fundamentals apply (Google Search Central). There is also no evidence that it increases citations in ChatGPT or Perplexity. If you want to know whether it does anything, check your own access logs, as in Section 9.
Q. Are there WordPress plugins for this?
Yes. The llmstxt.org list includes Yoast SEO and AIOSEO as WordPress plugins with llms.txt generation (as of September 29, 2026). Whichever you use, always review the generated output. You can also do it yourself with a few dozen lines in functions.php, so a plugin is not strictly necessary.