# AcademicPositions Job Scraper — EU Academic Jobs (`jobsapi/academicpositions-jobs-search-scraper`) Actor

Extracts public academic and research vacancies from Academic Positions listing and detail pages.

- **URL**: https://apify.com/jobsapi/academicpositions-jobs-search-scraper.md
- **Developed by:** [Jobs API](https://apify.com/jobsapi) (community)
- **Security:** Limited permissions
- **Stats:** 3 total users, 2 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 academic positions opportunities

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does AcademicPositions Job Scraper do?

AcademicPositions Job Scraper extracts **public academic, research, faculty, PhD, and postdoctoral vacancies from [Academic Positions](https://academicpositions.com/find-jobs)**. It provides a structured Academic Positions API alternative with job titles, employers, locations, descriptions, dates, employment types, and canonical links.

The canonical listing can challenge simple automated clients, so the default uses `r.jina.ai` strictly as a public text reader for that Academic Positions URL. Discovered public `/ad/` links are first fetched directly from the regional Academic Positions host and parsed from first-party JobPosting JSON-LD. If a cloud runtime receives HTTP 403, the Actor uses the validated public reader for that exact detail URL and reports `detailAccessMode: "public-reader"`. No account, private endpoint, CAPTCHA solver, or access-control bypass is used.

### Why use this Academic Positions scraper?

Use it to monitor European academic hiring, build research-job alerts, compare application deadlines, study institutional demand, or feed public vacancies into recruiting workflows. Apify adds scheduling, REST API access, webhooks, integrations, monitoring, and dataset downloads.

### What data can it extract?

| Field | Type | Description |
| --- | --- | --- |
| `jobId` | string | Stable public job identifier |
| `title`, `description` | string | Position title and public description |
| `company`, `location` | string | Employer and advertised location |
| `datePosted`, `validThrough` | string | Publication and closing dates |
| `employmentType`, `jobLocationType` | string | Published work classifications |
| `industry` | string | Source-provided academic field or industry |
| `jobUrl`, `sourceUrl` | string | Detail and discovery URLs |

Optional source values are omitted when unavailable. Every stored record must include a stable ID, title, job URL, source label, and extraction timestamp.

### How to scrape Academic Positions jobs

1. Open the Actor in Apify Console.
2. Keep the default public listing reader URL, or provide an HTTPS Academic Positions listing/detail URL.
3. Set `maxJobs` to a small number for the first run.
4. Choose a per-request timeout between 10 and 120 seconds.
5. Start the Actor and inspect the dataset in the Output tab.
6. Schedule or call the Actor through the API after confirming results.

Only supported Academic Positions regional domains and the configured reader path are accepted. This prevents arbitrary network requests.

### How much will it cost?

Cost depends on the current Actor pricing and your Apify plan. A listing run makes one discovery request and up to one detail request per selected job. `maxJobs` is capped at 50 and is the primary cost boundary. Start with five jobs before scaling.

### Input

```json
{
  "startUrls": [
    {"url": "https://r.jina.ai/http://academicpositions.com/find-jobs"}
  ],
  "maxJobs": 5,
  "requestTimeoutSeconds": 30,
  "proxyConfiguration": {"useApifyProxy": false}
}
```

### Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

```json
{
  "jobId": "123456",
  "title": "Postdoctoral Researcher",
  "company": "Example University",
  "location": "Stockholm, Sweden",
  "employmentType": "FULL_TIME",
  "datePosted": "2026-08-01",
  "validThrough": "2026-09-30",
  "jobUrl": "https://academicpositions.se/ad/example/2026/postdoc/123456",
  "source": "academicpositions.com",
  "scrapedAt": "2026-08-31T00:00:00.000Z"
}
```

### Tips and advanced options

Multiple start URLs are deduplicated. Direct detail URLs are useful for targeted extraction; listing URLs support bounded discovery. Temporary network, HTTP 429, and server failures are retried with backoff. Proxy configuration remains available when the account permits external proxy access, but the default reader fallback does not require that entitlement.

### FAQ, disclaimer, and support

The Actor reads public vacancy pages only. It does not log in, apply for jobs, solve CAPTCHAs, or access candidate data. Source structure and access policies can change; report repeatable issues through the Issues tab and use the API tab for programmatic access.

Public job posts may contain personal data protected by the GDPR and other laws. Process data only for a legitimate purpose, follow Academic Positions' terms and policies, and consult legal counsel if unsure.

# Actor input Schema

## `startUrls` (type: `array`):

Public Academic Positions listing or job-detail URLs. The default uses r.jina.ai only as a public reader for the canonical Academic Positions listing.

## `maxJobs` (type: `integer`):

Maximum public job postings to emit.

## `requestTimeoutSeconds` (type: `integer`):

Maximum time allowed for each public request.

## `proxyConfiguration` (type: `object`):

Optional proxy settings. The Actor also has a bounded public-reader fallback for blocked detail pages.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://r.jina.ai/http://academicpositions.com/find-jobs"
    }
  ],
  "maxJobs": 5,
  "requestTimeoutSeconds": 45,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("jobsapi/academicpositions-jobs-search-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("jobsapi/academicpositions-jobs-search-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call jobsapi/academicpositions-jobs-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jobsapi/academicpositions-jobs-search-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/4doAsU0Iewey0Ehc7/builds/yE4KHZfzVhnvzGjjr/openapi.json
