RSS to JSON
RSS and Atom are two dialects of the same idea, written twenty years apart, and every consumer of feeds eventually has to handle both plus the malformed feeds in between. This endpoint fetches a feed URL and returns its items as flat, predictable JSON, so your code never has to touch an XML parser again.
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
One feed spec became two, then a mess
RSS shipped in the late 1990s as a simple way to publish a list of updates, and it forked into competing versions (0.91, 1.0, 2.0) before Atom arrived in 2005 to fix RSS's ambiguities with a stricter spec. Both are still in daily use — a WordPress blog emits RSS 2.0 by default, a lot of publishing tooling emits Atom — and a real-world aggregator has to accept either one plus the countless feeds that violate their own spec with missing namespaces or malformed dates. Writing that parser once, correctly, is a bigger job than it looks.
What comes back from the call
POST a feed URL to /web/rss-to-json and you get a task_id right away while the feed is fetched and parsed in the background. The finished JSON normalizes the feed's title, link and description alongside every item — title, link, publish date, author and content — in one flat structure whether the source was RSS or Atom, so downstream code doesn't need to branch on which dialect it received. Results land at your webhook or a signed link valid for 24 hours.
Who actually needs this
A newsletter tool assembling a daily digest from twenty publisher feeds, a dashboard that shows the latest posts from a client's blog, or a research script tracking how often a set of news outlets publish on a topic all hit the same wall: feeds are XML, and most modern stacks would rather work with JSON than parse XML by hand or pull in a heavyweight library just for this. Normalizing at the point of ingestion means the rest of the pipeline stays simple.
Fitting it into automation
Because the task is async and billed per request, a scheduler can poll a hundred feeds every hour without anyone babysitting a cron job that occasionally chokes on a malformed XML document. A feed that returns nothing parseable simply reports a clean failure rather than crashing a script, and failed fetches are never charged — so a watchlist that includes a few dead or misconfigured feeds doesn't quietly waste budget on the ones that never respond.
What you can do with it
Daily digest newsletter
Pull the latest items from a list of publisher feeds each morning and assemble them into a single JSON payload for a newsletter template.
Client blog widget
Fetch a client's RSS feed on a schedule to power a 'latest posts' widget without embedding a live XML parser in the frontend.
Competitive publishing cadence tracking
Monitor how often a set of news or industry feeds publish new items to measure competitor output over time.
Podcast and blog cross-posting
Normalize a mix of RSS and Atom feeds from different platforms into one JSON shape before republishing selected items elsewhere.
FAQ
How do I convert RSS to JSON with the API?
POST the feed URL to /web/rss-to-json, keep the returned task_id, and collect the parsed JSON by webhook or a signed link valid for 24 hours.
Is the RSS to JSON API free?
No, there is no free tier or trial; it costs $0.002 per request, and a failed parse is never charged.
Does it support Atom feeds too, not just RSS?
Yes, both RSS (0.91, 1.0, 2.0) and Atom feeds are parsed into the same flat JSON structure.
What happens if the feed URL is invalid or unreachable?
The task returns a clear error instead of a partial result, and since it failed, it is not charged.
Does it handle malformed or non-standard feeds?
It handles common real-world quirks in published feeds, but a feed that seriously violates the RSS or Atom spec may still fail to parse cleanly.
Can I convert many feeds in bulk on a schedule?
Yes, submit one async task per feed URL on whatever schedule you need and collect each result by webhook as it completes.
What fields are included in the JSON output?
Feed-level title, link and description, plus per-item title, link, publish date, author and content, normalized the same way regardless of source format.
Is the fetched feed content stored afterward?
No, fetched feeds and parsed data are deleted after the retention window and are never used for training.
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, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/web/rss-to-json \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"…"}'const res = await fetch("https://api.kit.forhosting.com/web/rss-to-json", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"input": "…"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/web/rss-to-json",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"input": "…"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/web/rss-to-json", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"input":"…"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"input":"…"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/web/rss-to-json", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"input": "…"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "web.rss_to_json",
"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. |