EU Pay Transparency Compliance Checker avatar

EU Pay Transparency Compliance Checker

Pricing

from $4.00 / 1,000 job advert checkeds

Go to Apify Store
EU Pay Transparency Compliance Checker

EU Pay Transparency Compliance Checker

Audit any company's job adverts against the EU Pay Transparency Directive. Flags missing salary ranges, vague pay wording, and illegal pay-history questions. Reads public ATS feeds from Greenhouse, Lever, Ashby, Recruitee and Personio. No login or API key needed.

Pricing

from $4.00 / 1,000 job advert checkeds

Rating

0.0

(0)

Developer

Mike Zyke

Mike Zyke

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Audit any company's job adverts against the EU Pay Transparency Directive — every open role, in seconds.

Since 7 June 2026, employers hiring in the EU must state the salary or salary range for a role. "Competitive salary" no longer satisfies the law. Penalties reach the five- to six-figure range per breach, and in a pay dispute the burden of proof falls on the employer.

Point this Actor at a careers page. It tells you, role by role, whether the pay disclosure holds up.


Real example

A live scan of a Berlin AI company's job board (16 open roles, all EU):

JobStatusPay found
Senior Computer Vision Engineer✅ compliant€80,000 – €120,000 / year
Senior Backend Engineer✅ compliant€70,000 – €90,000 / year
Account Executive✅ compliant€70,000 – €90,000 / year
Sales Development Representative✅ compliant€40,000 – €50,000 / year
Field Installation Engineer✅ compliant€45,000 – €58,000 / year
Senior/Staff Robotics Engineerno pay disclosed
VLM Research Engineerno pay disclosed
Senior Edge Infrastructure Engineerno pay disclosed

Compliance score: 69% — 11 of 16 roles disclosed pay. Five did not, including one posted after the directive took effect.

That is the report. One run, no configuration.


What you get

One row per job:

FieldExample
complianceStatuscompliant · review · non_compliant · out_of_scope
issueCodes["VAGUE_PAY_LANGUAGE"]
salaryMin / salaryMax70000 / 90000
salaryCurrency / salaryIntervalEUR / year
salaryEvidencethe exact text the figure came from
jurisdictionEU · US-transparency-state · unknown
applyUrldirect link to the advert

Plus one company_summary row per employer with a 0–100 score.

{
"recordType": "job",
"company": "almetra",
"title": "Senior Backend Engineer (m/f/d)",
"location": "Berlin",
"complianceStatus": "compliant",
"issueCodes": [],
"salaryMin": 70000,
"salaryMax": 90000,
"salaryCurrency": "EUR",
"salaryInterval": "year",
"salarySource": "ats_field",
"jurisdiction": "EU",
"jurisdictionConfidence": "high",
"applyUrl": "https://jobs.ashbyhq.com/almetra/ec1bfd2d-..."
}

What it catches

IssueMeaning
NO_PAY_INFORMATIONNo pay figure anywhere in the advert
VAGUE_PAY_LANGUAGE"Competitive salary", "attraktives Gehalt", "salaire compétitif", "según experiencia" — 60+ phrases across 8 languages
RANGE_TOO_WIDE€30k–€120k. Technically a range; arguably not informative. Threshold configurable
SINGLE_VALUE_ONLYOne figure, no range
SALARY_HISTORY_QUESTIONAsking what a candidate currently earns — banned outright by Art. 5(2)
AI_DETECTED_PAYFound by AI review but not deterministic rules — verify before relying on it

Pay parsing built for European adverts

European job ads write money in ways that break naive parsing. 45.000 means forty-five thousand in Berlin and forty-five point zero in Boston. All of these are handled:

45,000 – €60,000 per year 55.000 EUR bis 70.000 EUR
zwischen 55.000 € und 70.00040 000 € à 55 000 € par an
3.500 tot € 4.500 per maand 15 000 - 22 000 PLN
85k - 110k $255k - $290k per year

Numbers that are not pay — headcounts, funding rounds, version numbers, "up to 6% matching" — are ignored.


Who uses this

  • HR and compliance teams — audit your own postings before a regulator or candidate does
  • Recruitment agencies — check client adverts before they go live
  • Pay-equity and HR-tech vendors — a live external signal alongside internal payroll analysis
  • Sales teams — set onlyNonCompliant: true for a prospecting list of companies with a visible, dated problem
  • Journalists and researchers — measure real compliance rates across an industry or country

Supported job boards

Reads the public, keyless JSON feeds each ATS publishes so customers can embed job widgets on their own sites. No login, no API key, no HTML scraping, no anti-bot fight.

ATSIdentifierNotes
Greenhousegreenhouse:stripeWidely used by tech
Leverlever:netflix
Ashbyashby:notionExposes structured salary data
Recruiteerecruitee:acmeCommon with EU scale-ups
Personiopersonio:acmeCommon with German mid-market

Accepts ats:slug, a full board URL (https://jobs.lever.co/netflix), or a bare slug to auto-detect.


Input

{
"companies": ["ashby:almetra", "greenhouse:stripe"],
"onlyNonCompliant": false,
"maxRangeRatio": 2.0
}
OptionDefaultNotes
companiesRequired. Slugs, URLs, or ats:slug
atsHintautoForce a platform instead of probing
maxJobsPerCompany200Stops one large board dominating a run
onlyNonCompliantfalseOutput only problem roles
maxRangeRatio2.0Flag bands wider than this multiple
assumeEuOnlyfalseSkip jurisdiction detection, check everything
useAiReviewtrueOnly used where rules find nothing
geminiApiKeyOptional. Blank = rules-only

Optional AI review

The rules engine is deterministic and conservative: it reports only pay it can prove is there. A minority of adverts bury pay in prose or phrase it unusually.

Add a free Gemini API key and those get a second look — only on jobs the rules engine could not resolve, so cost scales with ambiguity, not volume.

Three safety rules, each covered by tests:

  1. The model can never overturn a deterministic extraction. A hallucinated figure cannot overwrite a real one.
  2. An AI-only finding is capped at review, never compliant. A human confirms.
  3. Low-confidence verdicts are discarded.

No key? Everything still works. You'll just see slightly more NO_PAY_INFORMATION on unusually worded adverts.

Model availability is handled for you. Google retires Gemini models on a fast cycle and blocks older ones for newly created API keys. If the selected model isn't available to your key, the Actor logs a warning, switches to the next current model automatically, and carries on. If none are reachable it drops to rules-only rather than failing the run.


Pricing

Pay-per-event. Boards that return nothing cost nothing.

EventCharged when
company-scannedA board resolves successfully
job-checkedA job is analysed and returned
ai-reviewOnly when AI review actually changed a verdict

Scope and limitations

Read this before acting on the output.

A non_compliant result is a risk flag, not proof of a breach. Article 5(1) lets an employer disclose pay before the first interview instead of in the advert. This Actor can only observe the advert. Some member states (Ireland and the Netherlands among them) go further and require it in the advert itself — but the base directive does not.

Also:

  • Heuristics, not legal advice. A screening tool for human review.
  • Jurisdiction is inferred from location text and can be wrong, especially for "Remote" roles. Use assumeEuOnly when you already know the board's scope.
  • maxRangeRatio is a judgement call, not a legal threshold. The directive doesn't define a maximum width.
  • Only published jobs appear in public ATS feeds. Internal or unlisted roles are invisible.
  • Company data only. No personal data about applicants or employees is collected.
  • Pay-gap reporting duties (Art. 9) apply to employers with 100+ staff and are assessed from internal payroll — outside what any external tool can see.

Every endpoint used is the public, unauthenticated feed each ATS provides so that customer job boards can be embedded and syndicated. This is the same data any visitor sees on the company's careers page. No authentication is bypassed, no personal data is collected, and no login-walled content is accessed.


FAQ

Does this need an API key or login? No. The ATS feeds are public and keyless. The Gemini key is optional.

Can it check LinkedIn or Indeed job ads? No. It reads employers' own ATS feeds, which are published for syndication. Aggregator sites prohibit scraping.

Why is a job marked out_of_scope? The role appears to sit outside the EU/EEA and outside a US pay-transparency state, so no disclosure duty applies. Set assumeEuOnly: true to check everything regardless.

A company scored badly — are they breaking the law? Not necessarily. See Scope and limitations above. They may disclose pay before interview, which the directive permits.

How do I find a company's slug? Look at their careers page URL. boards.greenhouse.io/acmegreenhouse:acme. jobs.ashbyhq.com/acmeashby:acme. You can also paste the full URL.


Development

npm install
npm test # 54 tests, no network required
apify run
apify push
src/
main.js orchestration, billing, dataset output
ats.js one adapter per ATS, normalised to a common shape
compliance.js rules engine — extraction, checks, scoring
gemini.js optional AI adjudication + safe merge
logger.js SDK-safe logging shim
text.js HTML/entity handling, interval normalisation