Swell Cabin › Developers

Swell Cabin API

A free JSON API with no key: 130 surf towns and 492 surf spots worldwide, a 7-day surf forecast rated for each spot, places to stay, what the surf cams show and where the surf is good now. HTTPS, open to browsers (CORS). Every answer is the same data the site shows, with a link to the town's page.

Start here

curl 'https://swellcabin.com/api/towns?q=portugal&month=10'
curl 'https://swellcabin.com/api/forecast?town=ericeira'

GET /api/towns

Surf towns, filtered.

ParameterWhat it is
qoptionalText: town, country or region
regionoptionalRegion name
monthoptionalGood surf in this month: towns in season then, ranked by measured good + great days that month, each with inMonth { goodDays, greatDays, seaTempC, waveHeightM }
leveloptionalbeginner | intermediate | advanced
breakoptionalbeach | reef | point | rivermouth

Try it: /api/towns?q=portugal&month=10

Answer: Towns

GET /api/towns/{slug}

One town with its surf spots, and surfByMonth: how often the surf was good and great in each month, measured over the last three years.

ParameterWhat it is
slugrequired

Try it: /api/towns/ericeira?slug=

Answer: Town

GET /api/places

Places to stay (hotels, hostels, surf camps, homestays...), cafés, food or surf shops/schools near a town; reviewed photos come as photo { thumb, page, author, license }.

ParameterWhat it is
townrequiredTown slug
categoryoptionalstay | coffee | food | surf | spots
radiusKmoptionalSearch radius

Try it: /api/places?town=ericeira

Answer: Places, nearest first

GET /api/events

What's on: weekly nights and upcoming events in a town.

ParameterWhat it is
townrequiredTown slug

Try it: /api/events?town=ericeira

Answer: Weekly schedule and events

GET /api/feed

A town's Feed: recent YouTube surf videos about the town (last 30 days, at most two per channel), the latest posts from its local Instagram accounts and public Bluesky/Mastodon posts, each through Swell Cabin's quality check (ads, off-topic, unwatched and repeated posts left out) and with langs (the languages it is written in, when clear; the site shows each visitor what is in English or their language); part=classics gives the surf clips picked for its breaks.

ParameterWhat it is
townrequiredTown slug, or "all" for every town at once (each video and post then has its town)
partoptionalvideos, posts or classics (optional) (videos, posts, classics)
reviewoptional1 to also list what the quality check left out, with why (dropped) (1)

Try it: /api/feed?town=ericeira

Answer: videos, posts, instagram { accounts, posts }, quality { checked, kept, dropped, langs }

GET /api/forecast

7-day surf forecast for a town and each of its spots, rated per spot hour by hour (Flat … Epic, best time, why): surf height, swell, wind, tides, model confidence. Add live=1 for the nearest buoy and airport wind report right now.

ParameterWhat it is
townrequiredTown slug

Try it: /api/forecast?town=ericeira

Answer: Forecast by day and for the next 48 hours

GET /api/surf-now

Where the surf is good around the world in the next days: towns whose best day from today is at least min (fair, good, great, epic), best and soonest first, with that day's rating at the best spot, the spot, its best time and the surf in words, and today's rating; from the forecast for every town, worked out twice a day.

ParameterWhat it is
minoptionalfair | good | great | epic (default good)
withinoptionalDays from today, 1–4 (default 3)
regionoptionalRegion name

Try it: /api/surf-now

Answer: generated, stale, towns [{ slug, name, lat, lng, url, best { date, when, rating, spot, from, to, surf }, today }]

GET /api/cam-now

What the surf cams show right now: every 3 hours in daylight an AI reads a still from each free surf cam and says what it shows in the forecast's own words (size, surface, surfers out, how sure) and what that means at the spot (Looks good, Surfable, Looks poor, Flat); the latest reading per spot from the last 3 hours, with the cam's link and what the forecast said then. A reading of a picture, not a measurement.

ParameterWhat it is
townoptionalTown slug; leave out for every town with a reading now
goodoptional1: only the spots that look good

Try it: /api/cam-now

Answer: One town: readings [{ spot, time, local, words, surface, crowd, sure, verdict, label, reason, cam, provider, forecast { words, rating, steps } }], leftOut; every town: towns [{ slug, name, url, readings }]

GET /api/social

Swell Cabin's social posts from its own data (swell alerts, the best day this week, the weekend's best towns, season openings, surf events, where to surf this month, town spotlights, about Swell Cabin, and the weekly stories), each written for Instagram, Facebook, Threads, X, Bluesky and Mastodon with its time, link and card image; without a town, the latest daily proposal and what is scheduled.

ParameterWhat it is
townoptionalTown slug (optional)

Try it: /api/social

Answer: posts [{ kind, summary, card, posts [{ channel, text, dueAt }], facts }]

GET /api/card

The image (PNG) for one of Swell Cabin's social posts, drawn from the query that /api/social gives each post (card, story).

ParameterWhat it is
krequiredKind: swell-alert, best-day, weekend, season, event, month, spotlight, intro, swell-track, numbers, locals, beginners, night or spot
rowoptionalOn a list, the row to draw as its own photo slide
foptionalstory for 1080×1920, og for the 1200×630 link preview (default 1080×1350) (story, og)

Answer: PNG image

GET /api/spot-photos

Photos of surf at each spot in a town, with credits.

ParameterWhat it is
townrequiredTown slug

Try it: /api/spot-photos?town=ericeira

Answer: Photos by spot name