AcademicPositions Job Scraper — EU Academic Jobs avatar

AcademicPositions Job Scraper — EU Academic Jobs

Pricing

from $6.50 / 1,000 job results

Go to Apify Store
AcademicPositions Job Scraper — EU Academic Jobs

AcademicPositions Job Scraper — EU Academic Jobs

Scrape postdoc jobs, PhD positions & faculty jobs from academicpositions.com (EU, UK & Switzerland). A real browser via residential proxy passes Cloudflare. Returns title, institution, location, field, salary, posted date & apply URL — with delta mode for new-only scheduled runs.

Pricing

from $6.50 / 1,000 job results

Rating

0.0

(0)

Developer

NomadDev

NomadDev

Maintained by Community

Actor stats

0

Bookmarked

7

Total users

3

Monthly active users

2 days ago

Last modified

Categories

Share

Fetch postdoc, PhD, faculty and early-career-researcher openings from academicpositions.com, covering institutions across the EU, UK and Switzerland.

Claude / Codex skill to describe and setup this actor: SKILL.md

How it works

academicpositions.com sits behind Cloudflare's bot protection, so this Actor drives a real headless browser (Playwright/Chromium) through an Apify Residential proxy to load pages the same way a person's browser would. Each posting is parsed from the page's structured JobPosting data (schema.org JSON-LD), with a plain-HTML fallback for the rare page that omits it — so results stay accurate even as the site's front-end layout changes.

What data does this Actor extract?

Each result is one flat JSON record per job posting:

FieldTypeDescription
titlestringJob title as posted
companystring | nullHiring institution name
locationstring | nullPosting location (city/region/country, or "remote" wording for remote roles)
fieldstring | nullResearch area / discipline the posting itself labels (e.g. "Physics", "Life sciences"), read verbatim from JSON-LD occupationalCategory/industry or a discipline chip — never inferred from the title
urlstringDirect link to the posting
postedAtstring | nullPosting date (ISO 8601, e.g. "2026-06-20"), when the source provides one
snippetstring | nullPlain-text excerpt of the job description
salarystring | nullHuman-readable pay summary (e.g. "3000-4200 EUR MONTH"), only when the posting discloses baseSalary — most academic postings don't, so usually null
salaryMin / salaryMaxnumber | nullStructured pay range endpoints from JSON-LD baseSalary, when present
salaryCurrencystring | nullCurrency code for the salary range (e.g. "EUR"), when present
globalIdstring | nullStable identifier (academicpositions:<detail-path>) for joining or comparing records
sourcestringAlways "academicpositions"

Fields come back as null (never an empty string) on the rare posting where the source doesn't provide that piece of data.

Every run also appends one uncharged control row after all job rows and writes the identical object to the default key-value store as RUN-SUMMARY. The row has recordType: "RUN-SUMMARY", schema nomad-agent-source-run-summary-v1, a status of complete, partial_rate_limited, empty_source, or listing_blocked, and reconciled listing/detail/proxy/job counters. Consumers should branch on recordType and must not parse the summary row as a job. A partial run can still contain valid complete job rows before its summary.

How to scrape academicpositions.com with this Actor

  1. Click Try for free / Run — the default input needs no changes.
  2. Optionally set a keyword, countryFilter or postedSince to narrow results, and adjust maxItems.
  3. Run it and export the dataset as JSON, CSV or Excel, or read it over the API.

Run it from your own code:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("nomad-agent/academicpositions-scraper").call(
run_input={"maxItems": 30, "keyword": "machine learning postdoc"})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["title"], "—", item["company"], item["url"])

Or a single HTTP call that runs the Actor and returns items in one response:

curl -X POST \
"https://api.apify.com/v2/acts/nomad-agent~academicpositions-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"maxItems": 30}'

Input

FieldTypeDefaultNotes
keywordstring(empty)Free-text query appended to the listing URL (e.g. "postdoc", "computer science"). Leave empty to scrape the default listing.
countryFilterstring(empty)Case-insensitive substring match on the extracted location field (e.g. "Germany"). Applied client-side, after extraction. Leave empty to keep every location.
postedSincestring(empty)Only return postings dated on or after this date (YYYY-MM-DD). Postings without a parseable date are kept, not dropped. Leave empty to disable.
maxItemsinteger30Maximum number of postings to return. Each returned posting is billed as one dataset result — capped at 500 per run.
proxyConfigurationobjectApify Residential proxyProxy used to load the site. Keep the Residential group selected — academicpositions.com blocks non-residential IPs.
startUrl (Advanced)stringhttps://academicpositions.com/find-jobsThe listing page the Actor starts from and harvests job links from. Change only to start from a specific saved-search URL instead of the default listing.
detailUrlContains (Advanced)string/ad/Only links whose URL contains this text are treated as job-detail pages. Change only if the site's URL structure changes and the Actor stops finding postings.
cacheTtlSeconds (Advanced)integer900Persistent listing-card cache duration, bounded to 10–30 minutes. Used only when the fresh listing is classified blocked; the summary remains listing_blocked. Complete detail records are cached for 24 hours and can only serve URLs present in the current fresh/fallback listing. Set 0 to disable both caches.
useResidentialProxy (Advanced, deprecated)booleantrueSuperseded by proxyConfiguration above. Still honored when proxyConfiguration is left unset, for older integrations.

Output example

{
"title": "Postdoctoral Researcher in Quantum Computing",
"company": "TU Delft",
"location": "Delft, Netherlands",
"field": "Physics",
"url": "https://academicpositions.com/ad/tu-delft/2026/postdoctoral-researcher-in-quantum-computing/12345",
"postedAt": "2026-06-20",
"snippet": "Join our lab working on superconducting qubits and scalable quantum error correction...",
"salary": null,
"salaryMin": null,
"salaryMax": null,
"salaryCurrency": null,
"globalId": "academicpositions:ad/tu-delft/2026/postdoctoral-researcher-in-quantum-computing/12345",
"source": "academicpositions"
}

Pricing

Pay per event: $0.02 per Actor start and $0.008 per posting returned ($8 / 1,000 postings, less on higher Apify plans — down to $6.50 / 1,000). 100 postings ≈ $0.82. No subscription, no rental — you pay only for what you fetch. The price covers the real headed browser + residential proxy each run needs to pass Cloudflare.

This Actor also routes every request through Apify's Residential proxy group (required to get past academicpositions.com's bot protection), which is billed separately by Apify against your account's residential proxy GB allowance in addition to the per-event charges above.

Integrations

Export results as JSON, CSV or Excel, pull them via the Apify API or run-sync-get-dataset-items, wire this Actor into Make, Zapier or n8n, or call it from AI agents through the Apify MCP server.

Use cases

  • Academic job boards and alert bots for postdocs, PhD candidates and faculty
  • University career-services aggregation
  • Research on hiring trends across EU/UK/CH institutions
  • Building a searchable database of research openings

FAQ

Is it legal to scrape academicpositions.com? This Actor reads only publicly available job postings — data any visitor can see without logging in. Review the target site's terms and your local regulations for your specific use case.

Do I need an account on academicpositions.com? No. Postings are fetched from public pages — no login, cookies or session tokens required.

Why does this Actor need a residential proxy? academicpositions.com fronts its pages with Cloudflare Bot Fight Mode, which blocks datacenter IPs outright. A residential exit IP plus a real browser is what reliably gets through the challenge.

How fresh is the data? Every run fetches live listings directly from the site — there's no cache.

Something broken or missing? Open an issue on the Actor's Issues tab — it is monitored and reliability fixes ship fast.


From the maker of Oink — an open-source, AI-powered job-search bot for Telegram that runs on these Actors. Try the free bot, get a managed instance at oinkjobsearch.com, or browse the full catalog of 50+ Actors.