Build an RSS, Atom, or JSON Feed discovery link tag
Feed discovery works best when a page explicitly points browsers, readers, and crawlers to its syndication endpoint.
Run — free
This builder takes a supported feed type and an absolute feed URL, selects the matching media type, escapes characters that could break an HTML attribute, and returns a complete link rel alternate element ready for the document head. It supports RSS, Atom, and JSON Feed while rejecting unknown formats and invalid non-web URLs instead of producing misleading markup.
Choose the feed format that matches the published document
A discovery tag is useful only when its type attribute accurately describes the resource at the URL. Select rss for an RSS XML document, atom for an Atom XML document, or json-feed for a JSON Feed document. The builder maps those choices to application/rss+xml, application/atom+xml, and application/feed+json respectively. It does not inspect or download the destination, so the selected format must reflect what your server actually returns. Keeping this declaration accurate helps feed readers decide whether they understand the resource before fetching or parsing it. It also avoids a common copy-and-paste mistake: advertising an Atom endpoint with the RSS media type, or exposing a JSON Feed URL as generic JSON. Unknown names are rejected rather than guessed because a plausible but incorrect type can make discovery harder to debug. If a site offers several formats, run the builder once for each endpoint and place every resulting element in the page head. Each tag then represents one genuine alternate representation that a compatible client can choose.
Provide the canonical public feed URL
Enter an absolute HTTP or HTTPS URL that a visitor's feed reader can reach, such as https://example.com/feed.xml. Absolute URLs are preferable in discovery metadata because copied pages, cached documents, and clients with different base-URL behavior still resolve the same feed endpoint. The builder trims surrounding whitespace, verifies that the value can be parsed as a URL, and rejects schemes such as file, data, or javascript. It preserves the supplied web URL in the result rather than silently rewriting its path, query, fragment, escaping style, or letter case. Characters that have special meaning inside an HTML attribute are encoded in the generated markup, so a query string containing an ampersand becomes safe source without changing the returned URL field. Validation here confirms the shape and scheme, not ownership, availability, content type, redirects, or TLS configuration. Test the published endpoint separately and make sure it returns the intended feed with a successful response. When moving a feed, update both the server redirect and this discovery tag so new subscribers begin with the current canonical address instead of relying permanently on redirection.
Place and verify the generated element
Copy the returned tag into the head of the HTML page whose feed you want clients to discover. The result uses rel="alternate", the standard format-specific media type, and the escaped feed URL as href. It deliberately omits a title because the requested inputs contain only format and URL; adding invented descriptive text would be less useful than letting a publisher choose language and wording in their own template. If your site has multiple feeds, such as a main publication feed and separate topic feeds, create one element per URL and consider adding meaningful titles in your application code where users need to distinguish them. View the delivered page source after deployment, because a template engine or content-security layer may transform markup even when the generated value is correct. Then try discovery with at least one feed reader and inspect the response headers from the feed endpoint. The browser tool and API run the same deterministic function, so identical inputs produce identical fields and markup. Automated builds can call the API for $0.002 per request, while interactive use can run locally in the browser without sending the URL for processing elsewhere.
What you can do with it
Add RSS discovery to a publication
Generate the head element for a blog or news site's RSS endpoint without memorizing its media type.
Advertise an Atom alternative
Build consistent discovery markup for an Atom feed exposed alongside other syndication formats.
Publish JSON Feed metadata
Use the registered JSON Feed media type in a correctly escaped alternate link element.
FAQ
Which feed types are supported?
The accepted values are rss, atom, and json-feed. Any other value returns an invalid input error.
What does an API request cost?
Each API request costs $0.002. The browser version runs locally for free.
Does this check whether the feed exists?
No. It validates the input and builds markup without making a network request.
Why must the feed URL be absolute?
An absolute HTTP or HTTPS URL remains unambiguous for feed readers regardless of the page or base URL from which they discover it.
Are special characters in the URL safe in the tag?
Yes. Characters with special meaning in an HTML attribute are escaped in the tag, while the separate url result preserves the trimmed input.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/web/link-rel-alternate-build \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"feed_type":"rss","url":"https://example.com/feed.xml"}'const res = await fetch("https://api.kit.forhosting.com/web/link-rel-alternate-build", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"feed_type": "rss",
"url": "https://example.com/feed.xml"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/web/link-rel-alternate-build",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"feed_type": "rss",
"url": "https://example.com/feed.xml"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/web/link-rel-alternate-build", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"feed_type":"rss","url":"https://example.com/feed.xml"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"feed_type":"rss","url":"https://example.com/feed.xml"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/web/link-rel-alternate-build", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"feed_type": "rss",
"url": "https://example.com/feed.xml"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "web.link_rel_alternate_build",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
timeout_sec | 30 |
max_crawl_pages | 25 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |