RSS, Atom and web feeds
Feed structure and required elements, item versus entry fields, the date and identifier rules that decide whether a reader shows your post once or twice, and how to validate a feed.
The two feed vocabularies
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Example Engineering</title>
<link>https://example.com/blog</link>
<description>Notes on building software.</description>
<language>en</language>
<atom:link href="https://example.com/feed.xml" rel="self" type="application/rss+xml"/>
<item>
<title>Parsing XML without surprises</title>
<link>https://example.com/blog/parsing-xml</link>
<guid isPermaLink="false">urn:example:post:1024</guid>
<pubDate>Fri, 18 Sep 2026 10:00:00 +0000</pubDate>
<description>A short summary for feed readers.</description>
</item>
</channel>
</rss><?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Example Engineering</title>
<link href="https://example.com/blog"/>
<link rel="self" href="https://example.com/atom.xml"/>
<updated>2026-09-18T10:00:00Z</updated>
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
<entry>
<title>Parsing XML without surprises</title>
<link href="https://example.com/blog/parsing-xml"/>
<id>urn:example:post:1024</id>
<updated>2026-09-18T10:00:00Z</updated>
<summary>A short summary for feed readers.</summary>
</entry>
</feed>The rules that decide whether readers behave
| Concern | RSS 2.0 | Atom | Rule |
|---|---|---|---|
| Identifier | guid | id | Must be unique and permanent; never reuse for a different post |
| Date format | RFC 822, for example Fri, 18 Sep 2026 10:00:00 +0000 | RFC 3339, for example 2026-09-18T10:00:00Z | The two formats are not interchangeable |
| Feed timestamp | Not required | updated required | Atom requires it; readers use it to poll |
| Content | description or content:encoded | content or summary | Escaping matters: HTML in a feed must be escaped or in CDATA |
| Self link | Optional extension | link rel="self" | Needed for correct fetching and caching |
| Language | language | xml:lang | Optional, but improves display |
| Pagination | Extension | link rel="next" | Large archives need it |
<!-- HTML inside a feed: escape it, or wrap it in CDATA -->
<description>A short summary with <strong>bold</strong> text.</description>
<description><![CDATA[A short summary with <strong>bold</strong> text.]]></description>
<!-- CDATA cannot contain the sequence that closes it, so splitting is required -->
<description><![CDATA[Use ]]]]><![CDATA[> to close a CDATA section.]]></description>Prefer escaping to CDATA. Escaped content survives XSLT, concatenation and naive string handling, whereas an embedded CDATA terminator inside a code sample is a classic source of broken feeds.
Publishing and validating
- Serve the feed with the correct content type:
application/rss+xmlorapplication/atom+xml. - Send a
Last-ModifiedorETagand honour conditional requests, so aggregators do not refetch everything. - Validate against the schema — the RSS validator or the Atom RELAX NG schema — before publishing.
- Keep the item order stable, newest first, and never reorder existing entries.
- Set a cache lifetime that matches your publishing cadence.
- Test with at least two real readers, because lenient parsing hides mistakes that a strict one exposes.
# validate structure and formatting
xmllint --noout feed.xml
xmllint --format feed.xml | head -30
# check the date format precisely
xmllint --xpath 'string(//item/pubDate)' feed.xml
# confirm the served content type
curl -sI https://example.com/feed.xml | grep -i content-type⚠️
The single most common feed bug is a
guid that changes on every request — for example one derived from a timestamp or a session. Every reader then treats the same article as new, and subscribers see the entire archive again.FAQ
Is the guid the URL?
It may be, using
isPermaLink="true" when the identifier is genuinely a permalink. Use a stable URN instead if the URL may change, and set isPermaLink="false".Should a feed carry full content or a summary?
Full content is friendlier to readers; a summary drives traffic to the site. Either is valid, but be consistent so readers do not flip between modes.
Related
Attributes vs child elements: modelling decisions SVG, XHTML and XML in the browser
Last refreshed 2026-09-18.