How to Integrate Adzuna's Free Job API Into Your Job Board

CleanJobData Engineering

TL;DR

Adzuna's Search API is genuinely free and self-serve — register at developer.adzuna.com for an app_id/app_key. Default limits are published (25 hits/min, 250/day, 1,000/week, 2,500/month), but for commercial use Adzuna's terms describe access as a 14-day trial to validate the data, after which a licence agreement may be required; attribution is mandatory. The real gotcha: description only returns a short snippet, not the full posting. Location is a display string plus a lat/lng pair, not structured city/state/country — and salary_is_predicted is a real flag worth reading before trusting a salary value.

Unlike most of what we've covered in this series — ATS APIs that need per-employer board tokens, or feeds like iCIMS's that need vendor approval — Adzuna's Search API is refreshingly simple to get started with: register, get a key, start querying. It's a job-board aggregator's API, not a direct ATS source, so the tradeoffs are different too. Here's the real shape of it.

Getting an API Key

Register at developer.adzuna.com and you get an app_id and app_key. We didn't find a separate application-review step, but you do accept Adzuna's terms, which matter for commercial use (see below). That's the entire setup step.

Fetching Jobs

curl "http://api.adzuna.com/v1/api/jobs/gb/search/1?app_id=YOUR_APP_ID&app_key=YOUR_APP_KEY&results_per_page=20&what=javascript%20developer&content-type=application/json"

Two things about the URL structure that aren't obvious from the params alone:

  • The country is a path segment, not a query param — gb, us, au, ca, de, fr, in, and others go directly in the URL (/jobs/{country}/search/1), not as a filter you pass in. Querying multiple countries means multiple requests to different URLs, not one request with a country list.
  • The page number is also a path segment (/search/1, /search/2, ...) — pagination isn't a page query param, it's baked into the URL itself.

The Response Shape

{
  "results": [
    {
      "id": "4837291056",
      "title": "Senior JavaScript Developer",
      "company": { "display_name": "Acme Inc" },
      "category": { "label": "IT Jobs", "tag": "it-jobs" },
      "location": {
        "area": ["UK", "London", "Central London"],
        "display_name": "Central London, London"
      },
      "description": "We are looking for a Senior JavaScript Developer to join...",
      "salary_min": 65000,
      "salary_max": 85000,
      "salary_is_predicted": "1",
      "contract_type": "permanent",
      "contract_time": "full_time",
      "created": "2026-07-01T09:00:00Z",
      "latitude": 51.5142,
      "longitude": -0.0931,
      "redirect_url": "https://www.adzuna.co.uk/jobs/land/ad/4837291056"
    }
  ]
}

Field-by-field:

  • id — stable, safe dedup key.
  • description — this is the field that trips people up. Adzuna's own docs are explicit: "we currently only provide a snippet of the job description in the response" (their docs literally read "snipped," evidently a typo for "snippet" — same point either way). There's no separate detail endpoint to get the full text either — what you get in search is what you get. If your product needs to display a complete job description, Adzuna's API structurally can't supply one; you'd need to follow redirect_url out to the original posting, which puts you back in scraping territory for that field specifically.
  • location — not structured city/state/country. area is an array running general-to-specific (["UK", "London", "Central London"]), and display_name is a pre-formatted string. There's no country_code, city_id, or similar — you get latitude/longitude as separate top-level fields, which helps for map placement but not for filtering by administrative region.
  • salary_min / salary_max — present when available, but check salary_is_predicted before trusting them. When it's "1", Adzuna is estimating the salary from similar postings, not reporting a number the employer actually disclosed. Treat predicted and disclosed salaries as different confidence levels if your product surfaces pay data — silently merging them misrepresents how certain that number actually is.
  • contract_type (permanent, contract, etc.) and contract_time (full_time, part_time) — two separate fields covering what's often one employment_type field elsewhere; map them together if you need a single normalized value.
  • redirect_url — the actual apply link. This is a genuine outbound link to the original posting (or Adzuna's own listing page for it), not an Adzuna-hosted apply flow.
  • category — Adzuna's own taxonomy (label/tag), not standardized against any external schema — useful for filtering within Adzuna's data, not for merging with categories from other sources.

The Real Pain Points

No full description, structurally. This is the biggest limitation for anything beyond a listings widget. A "view full details" page backed only by Adzuna's snippet will look thin compared to one backed by a direct ATS API.

Location needs real parsing work despite looking structured. The area array is genuinely useful as a hint, but it's not consistent in depth across postings or countries — some entries have three levels, some have two — so you can't reliably index into it by position (area[1] isn't always "the city").

Published limits, but a commercial-use catch. Adzuna's terms list default limits of 25 hits per minute, 250 per day, 1,000 per week and 2,500 per month, and say higher limits can be requested for commercial applications. They also describe the free access for commercial users as a 14-day trial strictly for validating data quality; beyond that a licence agreement may be required, and you must remove data acquired from Adzuna if the agreement ends. Attribution is mandatory: an "Adzuna" label (at least 116x23 px) linking to adzuna.co.uk, plus the "Adzuna Jobsworth" icon on salary estimates. We couldn't find public pricing for a licence. Read the terms of service before building a product on it, and don't treat the free key as permission to store or republish the data.

One country per request. If your product spans multiple countries, you're making one request per country, then merging results yourself — there's no single multi-country query.

When This Is Enough

For a lightweight "jobs near you" widget, a market-research dashboard, or a prototype that needs real job data fast, Adzuna's free API is a good fit within its published limits and terms — you can get a key quickly, and the data (title, company, approximate salary, location, apply link) covers a lot of common use cases.

When It Isn't

The moment you need full job descriptions, precise structured location for filtering, a reliable distinction between disclosed and estimated salary at scale, or coverage across the many countries and sources Adzuna doesn't touch, you're back to the same pattern covered elsewhere in this series: combining Adzuna with direct ATS sources like Greenhouse means reconciling yet another schema, on top of the ones you're already normalizing. A data API like CleanJobData sources directly from employer ATS platforms — full descriptions, structured city/state/country, and salary that's parsed from what the employer actually disclosed, not estimated — as one consistent schema instead of a growing pile of source-specific parsers.

Test it with live job data in the CleanJobData Playground or read the Jobs API reference.