Personio Jobs Scraper & API — Any Company avatar

Personio Jobs Scraper & API — Any Company

Pricing

from $0.90 / 1,000 results

Go to Apify Store
Personio Jobs Scraper & API — Any Company

Personio Jobs Scraper & API — Any Company

Scrape every open job from any company on Personio (jobs.personio.com). Give a company subdomain and get each position with full description, location, department, employment type and apply URL — from the public feed. Filter by title, location, remote. No proxy. JSON or CSV out.

Pricing

from $0.90 / 1,000 results

Rating

0.0

(0)

Developer

Muhamed Didovic

Muhamed Didovic

Maintained by Community

Actor stats

0

Bookmarked

4

Total users

3

Monthly active users

a day ago

Last modified

Categories

Share

Personio Jobs Scraper 🧭

Scrape every open job from any company hosted on Personio (jobs.personio.com) — title, full description, location, department, and apply URL — straight from Personio's public job feed. One feed per company returns every position, fully detailed. No login, no anti-bot, no browser.

How Personio Jobs Scraper works


Why use this scraper

  • Complete boards in one call. Personio publishes a single public feed per company — every open position, no pagination, no per-job fetches.
  • Full job detail in English. Each row carries the entire job — descriptionHtml + plain text (requested in English by default), location(s), department, seniority, schedule, employment type, and the apply URL.
  • Verify every input. A per-input coverage report (INPUT-REPORT.csv) shows link-by-link which companies returned jobs, which were empty, and which weren't Personio boards — and rows stay in your input order.
  • Fast and cheap. No proxies required (the API has no anti-bot), so runs are quick and your cost stays low.
  • Normalized schema. Output uses a consistent ATS schema shared with our other ATS scrapers (Ashby, Lever, SmartRecruiters, Personio, BambooHR) — write one parser, reuse it across every ATS.
  • Built-in filters. Narrow by title, location, department, employment type, remote, or posted date — applied before a row is emitted, so you only pay for matches.

Overview

Personio is a widely-used recruiting platform. Many European companies host their careers on Personio at https://{company}.jobs.personio.com. This actor reads each company's jobs through Personio's public job feed and emits one clean, normalized row per open job.


Supported inputs

Input typeExampleNotes
Board URLhttps://vodeno.jobs.personio.comThe company subdomain
Bare subdomainvodeno, get-eThe part before .jobs.personio.com

Provide them in Start URLs and/or Organization slugs. Mix as many companies as you like in one run.

Where's the subdomain? It's the part before .jobs.personio.com in the careers URL.


Use cases

  • Job boards & aggregators — ingest fresh, structured roles from many companies.
  • Recruiting & sourcing tools — track who's hiring for what.
  • Market & talent intelligence — hiring velocity, remote-vs-onsite mix.
  • Lead generation — companies actively hiring are buying signals for many B2B products.
  • Personal job search — pull every role across your target companies into one sheet.

How it works

  1. Resolve each input to a Personio company subdomain.
  2. Fetch https://{company}.jobs.personio.com/xml?language=en — one feed per company. Requesting a language also returns full descriptions for boards whose default feed ships them blank.
  3. Parse every <position> inline (descriptions are included in the feed).
  4. Normalize to a common ATS schema and push one row per job, in input order.

Companies are fetched in parallel with a sliding-window concurrency cap, then emitted in the order you supplied them. Every run also writes a per-input coverage report (see Run coverage report). No proxy is needed; you can supply one for IP rotation at very large scale.


Input configuration

FieldTypeDefaultDescription
startUrlsarrayPersonio board URLs or company subdomains (strings or {url} objects).
organizationsarrayBare Personio company subdomains, e.g. ["vodeno","get-e"]. Merged with startUrls.
maxItemsinteger5000Max job rows emitted across the whole run.
maxConcurrencyinteger10How many companies to fetch in parallel.
titleKeywordstringKeep only jobs whose title contains this.
locationstringKeep only jobs whose location contains this.
departmentstringKeep only jobs whose department contains this.
employmentTypestringKeep only jobs matching this — matches Personio's schedule (Full-time / Part-time) or employment type (Permanent / Intern / Trainee / Freelance / Working student).
remoteOnlybooleanfalseKeep only remote jobs.
postedAfterstringKeep only jobs published on/after this date (YYYY-MM-DD).
includeDescriptionbooleantrueInclude descriptionHtml + descriptionText. Turn off for leaner/cheaper rows.
languagestringenFeed language (ISO code). Defaults to en, which also fills in descriptions many boards leave blank in their default feed. Leave empty to use each board's own language.
includeRawJsonbooleanfalseAttach the original Personio payload under raw.
proxyobjectOptional. Not required (no anti-bot); use only for IP rotation at scale.

Example input

{
"organizations": ["vodeno", "get-e"],
"maxItems": 500,
"remoteOnly": true
}

Output

One row per open job. Example (trimmed):

{
"ats": "personio",
"org": "vodeno",
"company": "Vodeno",
"subcompany": "Vodeno S.A.",
"jobId": "2538321",
"globalId": "personio:vodeno:2538321",
"title": "Business Development Manager/Director",
"department": "Sales",
"team": "Sales",
"occupation": "international_sales",
"occupationCategory": "sales_and_business_development",
"keywords": ["Business Development", "Sales"],
"employmentType": "permanent",
"schedule": "full-time",
"seniority": "experienced",
"yearsOfExperience": "3-5",
"workplaceType": null,
"isRemote": null,
"location": "Berlin, Germany",
"locations": ["Berlin, Germany"],
"descriptionHtml": "<h3>Your mission</h3>…",
"descriptionText": "Your mission…",
"publishedAt": "2026-02-20T11:30:02+00:00",
"jobUrl": "https://vodeno.jobs.personio.com/job/2538321",
"applyUrl": "https://vodeno.jobs.personio.com/job/2538321",
"companyJobsFound": 14,
"companyOrder": 0,
"rowInCompany": 3,
"scrapedAt": "2026-06-14T18:23:00.000Z"
}

Key output fields

FieldDescription
atsAlways "personio" — the source platform.
orgCompany board identifier.
companyCompany display name (derived from the subdomain).
subcompanyLegal entity name when the feed carries one, e.g. "deskbird GmbH".
globalIdStable, unique key ats:org:jobId — use it to dedupe across runs.
titleJob title.
department / teamOrg grouping as set by the company.
occupation / occupationCategoryPersonio's role taxonomy (fine + coarse), e.g. international_sales / sales_and_business_development.
keywordsFree-text tags the company attached to the role (array, may be empty).
employmentTypePersonio's type: permanent / intern / trainee / freelance / working_student.
schedulefull-time / part-time / full-or-part-time.
seniority / yearsOfExperienceSeniority band + years-of-experience range, when set.
workplaceType / isRemoteRemote / Hybrid / OnSite + a boolean remote flag.
location / locationsPrimary location + every listed location (including additional offices).
descriptionHtml / descriptionTextFull job description as HTML and plain text.
publishedAtWhen the role was published (ISO).
jobUrl / applyUrlPublic posting URL + application URL.
companyJobsFoundTotal open roles found for this company (before filters/maxItems).
companyOrder / rowInCompanyInput position of the company + order of the job within it — sort by these to restore exact input order.

Run coverage report

Every run also writes a per-input coverage report to the run's key-value store, so you can verify link-by-link which inputs produced jobs and which did not:

  • INPUT-REPORT.csv — opens directly in Excel / Google Sheets
  • INPUT-REPORT — the same data as JSON

One row per input you supplied, in input order:

ColumnMeaning
inputThe exact URL / slug you supplied.
statusok (jobs found) · empty (live board, 0 open roles) · failed (matched a Personio org but the fetch errored) · unmatched (not a Personio board — e.g. a Workday or generic careers page) · duplicate (same company as an earlier input).
orgResolved Personio subdomain (blank if unmatched).
jobsFoundOpen roles in the feed.
jobsEmittedRows actually output after filters + maxItems.
errorFailure reason, when status = failed.

Find it under the run's Storage → Key-value store.


FAQ

Do I need a proxy? No. Personio's job feed is public with no anti-bot. The proxy field is available only for optional IP rotation at very large scale.

Where does company come from? The Personio feed has no display name, so it's derived from the subdomain (e.g. vodenoVodeno).

Some jobs have no description — why? By default the actor requests the feed in English (language: "en"), which returns full descriptions even for boards whose default feed ships them blank. A few positions (e.g. talent-pool / evergreen postings) genuinely carry no description text; those still return every other field.

Can I force English (or another language)? Yes — set language to any ISO code (default en). Personio returns that language's descriptions where the company published them, falling back to its own default otherwise.

Can I scrape a company's own careers page, or a Workday / embedded page? This actor reads Personio boards at {company}.jobs.personio.com — paste that subdomain or its URL. A generic careers page or a different ATS (e.g. Workday) isn't scraped; it's flagged unmatched in the coverage report so you can spot it. If a company only embeds Personio on its own site, find the underlying {company}.jobs.personio.com address and use that.

How do I tell which of my input links returned jobs? Check the per-input coverage report (INPUT-REPORT.csv) in the run's key-value store — one row per link with its status and job counts. See Run coverage report.

Can it discover every company on Personio? No — Personio has no public directory of all boards (true for every ATS scraper). You supply the companies you care about.

How many jobs per company? Whatever they have open — each row carries companyJobsFound (the company's total), and you can cap total output with maxItems to control cost.

How fresh is the data? Live — every run hits Personio in real time.


Support

Found a bug or need a field added? Open an issue on the actor's Issues tab in the Apify Console.


Additional services

Need a different ATS or job board? We also build scrapers for Ashby, Greenhouse, Workday, Indeed, LinkedIn, Glassdoor, and many more. Check our Apify Store profile.


Explore more scrapers

  • Ashby / Greenhouse / Lever Jobs Scrapers — open roles from those ATS platforms.
  • Workday Jobs Scraper — jobs from any Workday career site.
  • Indeed / LinkedIn / Glassdoor — the major job boards, fast and structured.

⚠️ Disclaimer

This actor collects only publicly available job-posting data exposed by Personio's own public job feed. It does not access private, authenticated, or personal data, and does not bypass any access control. You are responsible for using the scraped data in compliance with Personio's terms, the source companies' terms, and all applicable laws (including GDPR/CCPA). Use the data ethically and lawfully.


SEO Keywords

Personio scraper, Personio jobs scraper, jobs.personio.com scraper, Personio job feed, Personio ATS scraper, scrape Personio jobs, Personio careers scraper, ATS job scraper, Europe jobs scraper, job postings API, company careers scraper, hiring data, recruiting data.