Public
Scrapes a cat adoption site and returns cats as JSON
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

🐱 PAWS Cat Adoption RSS Feed

Scrapes the PAWS adoptable cats page and republishes the listing as an RSS 2.0 feed — one item per cat, with a plain-text summary and a rich HTML card (photo + details + link back to PAWS).

Endpoint

PathBehavior
/feed.xmlThe RSS feed (Content-Type: application/rss+xml).
/302 redirect to /feed.xml (preserves query string).
anything else404 Not found.

Query params

ParamEffect
?sex=…Filter to male / female (also accepts m / f). Invalid values return 400.
?kitten=1Kittens only — drop any cat whose age mentions year. Cats with no listed age (typically adoption-pending) are kept. Also accepts true / yes / on.
?fresh=1Bypass the 5-minute server cache and re-scrape immediately.
?url=…Scrape a different listing URL (always uncached).

Feed shape

Each <item> includes:

  • <title> — Name — Sex, Age (with (adoption pending) suffix when applicable). Example: Bahama — Female, 5 years 2 months.
  • <link> — the cat's PAWS detail page (or the listing URL when none exists).
  • <guid> — the detail URL (permalink) when available, otherwise a stable paws-cat:<name> token.
  • <enclosure> — the cat's photo URL.
  • <description> — a plain-text one-liner for list previews. Example: "Bahama is a 5 years 2 months old female Domestic Shorthair cat available for adoption at PAWS - Lynnwood."
  • <content:encoded> — a self-contained HTML card with photo, a labeled details table, and a "View on PAWS →" link. Styles are inlined so most readers render it correctly.

Adoption-pending cats show a name and photo but PAWS hides their details, so the other fields come back null and the title is suffixed with (adoption pending).

Refetch behavior

The feed asks readers to poll as often as they're willing to:

  • HTTP: Cache-Control: no-store, no-cache, must-revalidate, max-age=0 (plus Pragma/Expires for older clients).
  • RSS: <ttl>1</ttl> and the sy: syndication module's updatePeriod=hourly / updateFrequency=1.
  • lastBuildDate and pubDate are regenerated on every response so the feed always looks new.

A 5-minute server-side cache of the parsed cat list keeps us from hammering paws.org on every poll; it can be bypassed with ?fresh=1.

How it works

Rendering mermaid diagram...

Files

  • main.ts — HTTP routing, caching, query params, RSS XML generation.
  • scraper.ts — fetch + cheerio parsing of the PAWS markup into Cat objects.
  • test.ts — runs the scraper against the live site and prints a summary.

Notes

  • PAWS serves server-rendered HTML, so a plain fetch + cheerio works well — no headless browser needed.
  • The parser keys off PAWS's card-block__* CSS classes. If PAWS redesigns their site, update the selectors in scraper.ts.
  • Photos are hosted on Petango (PAWS's adoption management system); promo cards are filtered out by requiring the image URL to be on petango.com.