Deel Jobs API
How Deel's job boards actually work, what its RSC flight payload really contains, and what ?source=deel returns in the HyperJobs API.
Deel is best known as an Employer of Record and global payroll platform, and as
of 2026 it runs a real multi-tenant ATS of its own. Customer boards live at
jobs.deel.com/<slug> — Klarna, Dott and Offensive Security among them — and
the boards are genuinely public: one unauthenticated GET returns a whole board
with every description already in the response. No auth, no pagination, no
detail pass.
What the board looks like#
curl "https://jobs.deel.com/job-boards/<slug>" # 301 → /<slug>There is no JSON API — robots.txt disallows /api/ — and no JSON-LD. The board
is a Next.js app, and the data arrives as an RSC flight payload: a run of
self.__next_f.push([1,"…"]) chunks embedded in the HTML. Everything is in
there, including all the bodies. Klarna's board is 81 jobs and 81 descriptions
from that one call.
Parsing it is the whole job, and it bites in three places:
- Decode and concatenate before parsing anything. The chunks are JS string literals that split at arbitrary offsets — mid-row, mid-token, even mid-escape-sequence. Parse a chunk on its own and you get garbage.
- The rows are not newline-delimited. They look like
{hexId}:T{hexLength},{payload}, and the next row starts immediately after the payload with no newline between them. On Klarna, one newline precedes the first row and then 272,733 characters run with none. A newline-anchored scan finds the first description and nothing else, which reads as "the list ships one body and the other 80 need a detail fetch". It doesn't. It ships all 81. - That length is in bytes, not characters. Descriptions are full of multi-byte UTF-8 — curly quotes, "Nykøbing Falster", "Düsseldorf". Slice by character count and the parser desynchronises on the first one and silently corrupts every row after it.
Descriptions themselves are lazy references: a posting carries
richtextDescription: "$23", which points at row 23 in the same payload. Get
the three above right and all of them resolve locally, with no second request.
Pagination doesn't exist, and that was proven rather than assumed: ?page=2,
?offset=50 and ?limit=5 all return a byte-identical board. The completeness
was checked against an independent oracle — the per-org sitemap that robots.txt
advertises — at 81/81, 29/29 and 21/21 across three tenants.
What bites you#
The location is often a legal entity, not a place. Deel is an EoR, so the
field carries the contracting entity the employer typed: CellPoint Digital India LLP, Natural Capital Research Limited, Head Office - Calgary. Fed
straight to a location parser, 12 of 95 distinct values wrote company names
into the cities column. Stripping the org's own tokens and the entity suffix
recovers the real signal those strings carry — India, Calgary — rather than
throwing them away.
The workplace type is hidden in that same string. Deel publishes no
structured remote/hybrid field at all. What it has is Brussels, Belgium (Hybrid),
Tbilisi On-site, Remote - US. If you don't lift it out of the location, the
arrangement is simply lost.
Compensation has no period, and the periods are mixed on one board
currentCompensation is {currency, minAmount, maxAmount} and there is no
frequency key anywhere in the payload. Klarna lists SEK 55,206 (monthly)
beside SEK 752,814 (annual) in the same field, same currency, with nothing
distinguishing them. Assume a period and you store a Stockholm engineer's
monthly pay as their annual salary — a 12x error large enough to clear every
sanity check. Deel's own front-end renders these ranges period-less too.
So a Deel posting gets its compensation as text and no structured salary. A wrong salary is worse than none.
An unknown tenant returns HTTP 200, never a 404. It's a ~15KB shell. The only failure signal is the absence of the board props. A real but empty board is distinguishable — it ships its settings plus an empty postings array — but you have to look for the difference rather than trust the status code.
Deel itself is not a tenant of Deel. jobs.deel.com/deel redirects off the
platform to www.deel.com/careers, because Deel hires through Ashby.
What you get#
The flight payload parsed rather than worked around: every description resolved out of the one call its posting already came in, no detail pass, and after geocoding, full country coverage — 100% on both, measured across 29 tenants and 349 jobs. Deel is also one of the better platforms for the company join: about 46% of tenants publish a privacy-policy link that resolves to the employer's own domain, which is the only employer-domain signal the board exposes.
Query it with ?source=deel. The counts above are a measurement rather than a
promise, and they move — /v1/meta → sources is
the live vocabulary and the honest place to read both the value and the size of
it off.
See all platforms · coverage
Every source above normalises onto the same schema, with the hiring company already joined onto each posting.
Get an API key