Sports & Fitness — entry 027 of 33

Squiggle

Verified Jul 2026

Squiggle is a free JSON API for AFL fixtures, results, ladders, and its signature aggregated margin predictions pooled from multiple tipping models. Its own docs require setting a descriptive `User-Agent` containing a contact email rather than an API key, and since v1.11.0 the API actively refuses requests carrying common scraper user-agent strings, so `auth: None -> User-Agent` is corrected. A live Origin-header probe of the real host returned an explicit `{"error":"forbidden_origin"}` rejection for a cross-origin browser request -- reachable directly, but not CORS-open to arbitrary origins -- correcting `cors: yes -> no`.

Squiggle is a single-endpoint JSON API for AFL fixtures, results, ladders, and its signature aggregated margin predictions: every call hits the same root path with a q= parameter selecting the resource (teams, games, tips, ladder, and more). No API key is required, but the API actively rejects requests that don't self-identify with a descriptive User-Agent, and it refuses cross-origin browser calls outright regardless of UA.

aflaustralian-footballfixturespredictionsresults
AuthenticationUser-AgentSign up with the provider to obtain credentials.
HTTPSSupportedTraffic is encrypted in transit.
CORSDisabledBrowser calls need a server-side proxy.
PricingFreeNo paid tier — free for the documented use case.
FormatsJSONResponses can be requested as JSON.

GreatAPIs Score

Score71out of 100
Authentication22/25Only a User-Agent header
Pricing20/20Free to use
Docs0/20No docs or spec available
Formats9/15Single response format
Freshness20/20Verified within 6 months

Embed this badge

Scored 71 on greatapis.com
<a href="https://greatapis.com/api/squiggle/"><img src="https://greatapis.com/badge/squiggle.svg" alt="Scored 71 on greatapis.com"></a>

Auth quickstart

  1. No API key or signup, but every request must carry a descriptive User-Agent naming your app and a contact method. A live GET this run with the default curl/7.88.1 UA still returned HTTP 403, and the response body nests the rejection inside the requested resource's own key: {"teams":[{"api_version":"1.13.2","your_user_agent":"curl/7.88.1","error":"bad_UA","warning":"Your UserAgent has not been set correctly. To avoid bans, please see https://api.squiggle.com.au/#section_bots"}]} — swapping in a UA like greatapis.com quickstart (contact: hello@greatapis.com) returns the real data instead, confirmed live this run.
Stored keyNo key stored

Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.

List AFL teams

GEThttps://api.squiggle.com.au/?q=teams

User-Agent: greatapis.com quickstart (contact: hello@greatapis.com)

200 application/json; charset=UTF-8

{"teams":[{"retirement":9999,"logo":"/wp-content/themes/squiggle/assets/images/Adelaide.png","abbrev":"ADE","id":1,"debut":1991,"name":"Adelaide"},{"retirement":9999,"logo":"/wp-content/themes/squiggle/assets/images/Brisbane.png","abbrev":"BRI","id":2,"debut":1987,"name":"Brisbane Lions"},{"...":"16 more teams, same shape"}]}

Try it

Developer reference

Base URLhttps://api.squiggle.com.au
Key endpoints
  • GET/?q=teams
  • GET/?q=games&year={year}&round={round}
  • GET/?q=tips&year={year}&round={round}

Gotchas & limits

  • A rejected request due to a bad User-Agent is HTTP 403, but the error payload is nested inside the requested resource's own array key (teams/games/etc.), not a top-level error field — see the authSteps transcript above; a naive client that only checks response.ok before reading data.teams[0].name will silently render the error object as if it were a team.
  • Cross-origin browser calls are refused outright, independent of the User-Agent check: a live GET with a correct UA plus Origin: https://greatapis.com this run still returned HTTP 403 with {"teams":[{"api_version":"1.13.2","message":"Cross-origin browser access from this origin is not allowed.","error":"forbidden_origin"}]} — server-side or same-origin calls only, no CORS workaround exists client-side.
  • q=tips returns one row per tipster source per game, not one row per game: a live GET /?q=tips&year=2024&round=1 this run returned multiple entries sharing the same gameid (e.g. 35704), each from a different source ("Squiggle", "Matter of Stats", "Punters", ...) with its own margin/confidence — summing or averaging without grouping by gameid double-counts games.
  • The documented query syntax uses semicolons between parameters (?q=games;year=2024;round=1), but a live test this run confirmed standard &-separated query strings (?q=games&year=2024&round=1) return byte-identical results — either separator works against the real host.