EU Pay Transparency Job Ad Auditor: salary evidence avatar

EU Pay Transparency Job Ad Auditor: salary evidence

Pricing

from $5.00 / 1,000 postings

Go to Apify Store
EU Pay Transparency Job Ad Auditor: salary evidence

EU Pay Transparency Job Ad Auditor: salary evidence

I find stated pay, vague wording and pay-history requests across seven public ATS boards and career pages. Every finding includes source text. Missing advertised pay is a review flag, not a legal verdict.

Pricing

from $5.00 / 1,000 postings

Rating

0.0

(0)

Developer

Jessy Mariau

Jessy Mariau

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

3 days ago

Last modified

Categories

Share

EU Pay Transparency Job Ad Auditor

Review a company's job board without reading every advert into a spreadsheet. Get the pay figures found, any vague wording, and evidence of a pay-history request, with source text beside each result.

Missing pay in an advert is a review flag. It is not proof of a legal breach: the disclosure can happen before an interview, and national rules differ. This tool reads the public advert, not the employer's entire recruitment process.

See three sample results: leave all sources empty and run the demo with no Actor event charge. When you supply real postings, 100 readable adverts cost $0.50 in Actor events. Failed sources and unreadable postings are not charged. An optional OpenAI second pass uses your own key and has its own usage costs.

Sample output

These fictional adverts are bundled with the Actor. The table was checked against the actual demo output on 8 September 2026.

RolePay in advertPay-history requestReview status
Store Manager, AmsterdamEUR 42,000–48,000/yearNoOK
Head of Marketing, BerlinVagueNoATTENTION
Finance Analyst, ParisMissingYesREVIEW_REQUIRED

OK describes these text checks only. Open pay_evidence and history_evidence to review what was matched before taking action.

What it does

You give it job boards, career pages, single posting URLs, or any mix. It reads the postings and works out three things for each one.

Is pay stated? PROVIDED when there is an actual figure or range, VAGUE when the advert only gestures at pay with wording like competitive salary or à négocier or leistungsgerechte Vergütung, and MISSING when there is nothing. Figures are read from a structured field where the applicant tracking system publishes one, from JSON-LD baseSalary on a career page, and from the advert text otherwise. Text detection handles European number formats and currencies: 45.000 – 55.000 €, €45k-55k, 45 000 EUR brutto/Jahr, 25 000 - 32 000 zł miesięcznie, 450 000 kr per år. Vague wording is matched in English, German, French, Spanish, Italian, Dutch and Polish.

Does it ask for pay history? That is the Article 5(2) point, and it is kept strictly apart from asking what salary someone wants. "Gehaltsvorstellung", "prétentions salariales" and "salary expectations" are recorded in their own field and are never counted as a breach, because the directive bans asking about pay history, not pay expectations. A payroll job that lists "Gehaltsabrechnung" as a duty is not asking anyone for a payslip either, so document wording only counts when the advert is asking the applicant to send one.

Is the posting in the geographic filter? Country comes from the posting's own location field where it has one, from JSON-LD jobLocation, or from the location text. The geographic filter includes EU-27 plus Iceland, Liechtenstein and Norway; this does not determine national legal applicability. A role advertised across the Union with no single country is kept as EU rather than thrown away.

Those three combine into a verdict: OK when pay is stated and no pay history is asked for, ATTENTION when the wording is vague or pay is stated but history is asked for, REVIEW_REQUIRED when an in-scope posting states no pay at all, OUT_OF_SCOPE for a posting outside the EU and EEA, and UNREADABLE when the posting was fetched but carried no usable text.

Seven applicant tracking systems are read through their own public postings APIs:

  • Greenhouse
  • Lever
  • Ashby
  • Personio
  • Workable
  • SmartRecruiters
  • Recruitee

None of them needs a key or a login, and there is no proxy or browser anywhere in the chain.

What you need

Nothing. Every source is a public endpoint.

There is one optional field. If you paste an OpenAI key, postings where the rules found no pay wording at all get a second look from a model, which catches unusual phrasing and languages the lexicon does not cover. It never overrides a figure the rules already found, and rows it decided are marked pay_source: "llm" so you can tell them apart. Leave it empty and the audit runs in full.

Run it with no sources at all and you get three sample rows in demo mode, nothing charged, so you can see the shape before you point it at anything.

How to run it

Audit a few company boards:

{
"atsBoards": "greenhouse:getyourguide\nlever:qonto\npersonio:orderbird\nrecruitee:channable\nworkable:skroutz",
"maxPostingsPerSource": 50
}

The identifier after the colon is whatever that system puts in the board URL: the Greenhouse board token, the Lever site name, the Ashby job board name, the Personio subdomain, the Workable subdomain, the SmartRecruiters company identifier, the Recruitee company name.

Audit a career page and a single advert:

{
"careerPageUrls": "https://jobs.channable.com/",
"jobUrls": "https://jobs.channable.com/o/apar-specialist-join-our-finance-team",
"maxPostingsPerSource": 25
}

On a career page, JobPosting JSON-LD is read where the page publishes it, and job links on the page are followed where it does not.

The OUTPUT record in the key-value store holds the run summary: how many postings were audited and charged, the count for each verdict, a per-employer breakdown with the postings that ask for pay history listed out, and any source that returned nothing along with why.

Output fields

FieldWhat it holds
employer, title, urlthe company, the role, the live advert
sourcegreenhouse, lever, ashby, personio, workable, smartrecruiters, recruitee, or page
verdictOK, ATTENTION, REVIEW_REQUIRED, OUT_OF_SCOPE or UNREADABLE
pay_disclosedPROVIDED, VAGUE or MISSING
pay_min, pay_max, currency, periodthe parsed figures, ISO currency, and year, month, week, day or hour
pay_sourceats, json-ld, text or llm: where the pay finding came from
pay_evidencethe exact text the pay finding was matched on
asks_pay_history, history_evidencewhether the advert asks what the applicant earns or earned, and the sentence
asks_pay_expectations, expectations_evidencewhether it asks what they want, reported separately and never a breach
location_country, in_scope_eu_eea, remote, locationISO 3166-1 alpha-2 or EU, whether the location falls in the EU/EEA geography filter; not a legal scope determination, and the location as advertised
date_posted, department, employment_typeas published by the source
checked_at, errorwhen the row was produced, and why a posting could not be read

Pricing

Pay per event: one posting-audited charge per posting that was fetched and audited. A posting that came back with no usable text costs nothing, a board that 404s costs nothing, and a source that returns an error costs nothing. Demo mode is free.

Limits

This is a text audit of public job adverts. It is not legal advice, and it does not tell you whether an employer is breaking the law.

Three things worth being clear about. National rules vary, because member states transposed the directive at different times and some went further than the minimum, so what a given advert has to say depends on where the job is. The directive allows pay information before the interview rather than necessarily in the advert. Whether a particular employer meets the applicable national rules needs a separate review. And a MISSING verdict means one thing only: the posting itself does not state pay. Treat it as a place to look, not a finding.

Two practical limits on sources. Teamtailor is not supported, because its jobs API needs an API key issued per company; give the career page URL instead. Personio's public XML feed often ships with the description field empty, and its job pages sit behind a bot challenge, so a Personio board can come back UNREADABLE even though the adverts read fine in a browser. When that happens the run says so rather than guessing.

Sources that fail are reported by name with their HTTP status in source_errors, never quietly dropped.

Pair it with a workflow

If you run n8n, my free templates on https://n8n.io/creators/fractional-hq take a list like this Actor's output and turn it into lead scoring, outreach drafts and follow-ups without another tool in the chain.

There is a longer write-up of how the audit works, and what it deliberately does not claim, at https://fractionalhq.uk/use-cases/pay-transparency-audit

Directive text: https://eur-lex.europa.eu/eli/dir/2023/970/oj

Use it from an AI agent

Inside an AI agent this Actor works as an MCP server, which I set up for my own agents first. Add https://fractionalhqforyou--eu-pay-transparency-job-ad-auditor.apify.actor/mcp and call the single tool, audit_job_postings, with the same job ad URLs the input form takes. The audit costs the same per event whichever way it is started. If a raw endpoint cannot be added, apify/actors-mcp-server with fractionalhqforyou/eu-pay-transparency-job-ad-auditor in its list exposes the same tool.

Pay transparency sits beside two other EU obligations and one hiring signal, all of which have their own Actor here.

Built by Fractional HQ

Independent design and automation by Jessy Mariau. For setup or a custom integration, send a brief.

Output change, 8 September 2026

REVIEW_REQUIRED replaces LIKELY_NON_COMPLIANT for missing advertised pay. Update filters that used the old verdict. The pay and evidence fields keep their existing names. OK and ATTENTION remain text-review statuses, not legal conclusions.