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, get an app_id/app_key immediately, no approval process. The real gotcha: description only returns a short snippet, not the full posting, and there's no public rate-limit or pricing page for anything beyond that free key. 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're issued an app_id and app_key immediately — no application review, no waiting period. 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 paramgb, 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").

No published rate limits or commercial pricing. Adzuna's developer docs don't publish a requests-per-day or requests-per-minute ceiling for the free key, and there's no public pricing page for higher-volume or commercial use — you register, you get a key, and beyond that the terms aren't documented anywhere self-serve. Build in your own conservative rate limiting rather than assuming a specific ceiling, and expect to contact Adzuna directly if you outgrow casual use.

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 without an approval process, Adzuna's free API is a genuinely good fit — it's live in minutes, 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 explore the API Documentation.