# Jobs.ac.uk Scraper - UK Academic & PhD Jobs (`santamaria-automations/jobs-ac-uk-scraper`) Actor

Extract UK academic and research jobs from Jobs.ac.uk. Returns job title, employer (university), department, salary (min/max in GBP), grade band, employment type, contract type, closing date, position type (academic/research/PhD-studentship), academic rank, research field, and funding source.

- **URL**: https://apify.com/santamaria-automations/jobs-ac-uk-scraper.md
- **Developed by:** [NanoScrape](https://apify.com/santamaria-automations) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 1,000 serp results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Jobs.ac.uk Scraper

Extract UK academic and research vacancies from [Jobs.ac.uk](https://www.jobs.ac.uk), the primary board for UK universities, research institutes, and higher education professional services roles.

### What it does

Given search keywords and an optional UK location, the actor fetches the Jobs.ac.uk search results, follows each vacancy to its detail page, and returns a structured record per job. It handles four position types out of the box:

- Academic teaching (Lecturer, Senior Lecturer, Reader, Professor, Teaching Fellow)
- Research (Postdoc, Research Associate, Research Fellow, Research Assistant)
- Professional services and technical (managers, coordinators, technicians)
- PhD studentships (with stipend amount, duration, and supervisor extracted when present)

Deep-employer mode (`includeCompanyDetails: true`) also fetches the institution's `/search/employer/{slug}` page for the About-us copy, external website, and a list of the institution's other currently-open roles.

Salary is normalised to min/max/currency/period. UK academic Grade bands (like Grade 7, or Grade 8) that only appear as free text on the search card get parsed alongside the JSON-LD `baseSalary` on the detail page, so you get both the raw text and the numeric range.

### Sample output

```json
{
  "_type": "job",
  "id": "1085265",
  "title": "Lecturer in Computing Science",
  "employer_name": "Regent College London, part of the Regent Group",
  "department": "Academic",
  "location": "London, England",
  "country": "GB",
  "salary_min": 50000,
  "salary_max": 50000,
  "salary_currency": "GBP",
  "salary_period": "year",
  "salary_text": "Up to £50,000 per annum subject to skills and experience.",
  "employment_type": "full-time",
  "contract_type": "permanent",
  "position_type": "academic",
  "academic_rank": "Lecturer",
  "research_field": "Computing",
  "funding_source": null,
  "posted_at": "2026-08-18",
  "closing_at": "2026-10-17",
  "job_url": "https://www.jobs.ac.uk/job/DSQ504/lecturer-in-computing-science",
  "application_url": "https://www.jobs.ac.uk/job/DSQ504/lecturer-in-computing-science",
  "source_platform": "jobs.ac.uk",
  "scraped_at": "2026-08-19T10:05:06Z",
  "company_website": "https://www.regent.ac.uk/",
  "company_address_city": "London",
  "company_address_country": "GB",
  "company_active_jobs_count": 4
}
```

For PhD studentships the record also includes `stipend_amount_gbp`, `duration_years`, and (when the advert names them) `supervisor_name`.

### Pricing

Pay only for what you scrape. Apify credits the first $5 every month, which is enough for around 1,000 vacancies in Fast mode.

| Event | Price |
|-------|-------|
| Actor start | $0.001 |
| SERP result (Fast mode) | $0.003 |
| Detail result (Full mode) | $0.005 |
| Company detail (per unique employer, when `includeCompanyDetails: true`) | $0.005 |

Typical cost: **$3 per 1,000 jobs** in Fast mode, **$5 per 1,000 jobs** in Full mode.

### Input

The two common paths:

1. **Search URLs.** Search on jobs.ac.uk, copy the URL from your browser, paste into the `searchUrls` field. All filters travel with the URL.
2. **Keywords + location.** Fill `searchQueries` with terms like `postdoc chemistry` or `PhD studentship physics`, and `location` with a UK city.

```json
{
  "searchQueries": ["lecturer in computer science"],
  "location": "London",
  "maxResults": 100,
  "mode": "full",
  "includeCompanyDetails": true
}
```

`includeJobDetails: true` is equivalent to `mode: "full"` (both trigger detail-page fetches). `includeCompanyDetails: true` implies both : the employer link only lives on the PDP.

Use Fast mode when you only need the SERP fields (title, employer, salary text, dates). Use Full mode when you also need contract type, hours per week, full description, funding source, and PhD studentship extras.

### Output fields

| Field | Notes |
|-------|-------|
| `title` | Job title as advertised |
| `employer_name` | University or institute (from JSON-LD `hiringOrganization`) |
| `department` | School, faculty, or department name |
| `location` | City, region |
| `country` | Always `GB` |
| `salary_min`, `salary_max`, `salary_currency`, `salary_period` | Structured salary (GBP, per year by default) |
| `salary_text` | Original free-text salary line (keeps Grade band information) |
| `employment_type` | full-time, part-time |
| `contract_type` | fixed-term, permanent, open-ended, contract, temporary |
| `duration_months`, `duration_years`, `hours_per_week` | Contract detail from the advert table |
| `position_type` | academic, research, PhD-studentship, professional-services, technical |
| `academic_rank` | Lecturer, Senior Lecturer, Reader, Professor, Postdoc, Research Fellow, etc. |
| `research_field` | Best guess based on the vacancy title |
| `funding_source` | UKRI, EPSRC, BBSRC, Wellcome Trust, Leverhulme, and other councils detected in the advert body |
| `stipend_amount_gbp`, `supervisor_name` | PhD studentship extras when the advert names them |
| `posted_at`, `closing_at` | ISO dates |
| `job_url`, `application_url` | Direct links |
| `company_about` | About-us / mission text from the /search/employer institution page (deep-employer mode only) |
| `company_website` | External institution website (from PDP schema.org sameAs + fallback to first external link on the employer page) |
| `company_address_city`, `company_address_country` | From PDP schema.org jobLocation.address |
| `company_active_jobs_count`, `company_active_jobs` | Count + list of the institution's other open roles (deep-employer mode only) |
| `company_phone`, `company_email`, `company_address_street`, `company_address_postcode` | Usually null - jobs.ac.uk employer pages rarely expose these fields |

### Use with MCP

Connect your MCP-compatible client (Claude Desktop, Cursor) to the Apify MCP server and call the actor by slug:

```
Run the nanoscrape/jobs-ac-uk-scraper actor with:
  searchQueries = ["postdoc machine learning"]
  location = "Cambridge"
  maxResults = 50
  mode = "full"
```

The client will trigger a run and return the dataset as tool output.

### Why this scraper

- **Academic-native fields.** Position type, academic rank, funding council, and PhD studentship extras that generic job scrapers do not surface.
- **Full JSON-LD parse.** Salary, dates, and employer come from the schema.org `JobPosting` block on every advert, so numeric fields are consistent across universities.
- **UK Grade bands preserved.** `salary_text` keeps the "Grade 7, £39,347 to £46,485" phrasing that university HR systems use, alongside the parsed min/max range.
- **Low resource footprint.** 128 MB of memory per run, no browser needed, results in seconds.

### Common use cases

- Academic career market intelligence (who is hiring in a given field, at what grade)
- PhD studentship discovery for prospective students, with stipend and supervisor extraction
- Recruiter sourcing for higher education roles by rank and discipline
- Funding-council tracking (jobs backed by EPSRC, BBSRC, Wellcome, etc.)
- Lead generation for suppliers to UK universities (research equipment, HR platforms, digital services)

### Notes and limits

- Jobs.ac.uk paginates 25 vacancies per page. The actor stops when a page returns fewer than expected, or when `maxResults` is reached.
- Some employers only publish a Grade band, not a numeric range, in which case `salary_min` and `salary_max` will match a single number and `salary_text` carries the Grade context.
- Research field detection is a best-effort classifier based on the vacancy title. Combine with `department` for higher precision.
- Advert bodies vary wildly in structure. Description is captured as both HTML and plain text; funding source detection uses keyword hits in the description body.

### Related actors

- [Reed.co.uk Scraper](https://apify.com/santamaria-automations/reed-uk-scraper): private-sector UK vacancies across all industries.
- [NHS Jobs Scraper](https://apify.com/santamaria-automations/nhs-jobs-scraper): NHS clinical, medical, and healthcare support roles via the official XML API.
- [Guardian Jobs Scraper](https://apify.com/santamaria-automations/guardianjobs-scraper): media, charity, and public sector UK vacancies.
- [Website Email Scraper](https://apify.com/santamaria-automations/website-email-scraper): follow-up contact extraction on the employer domain.

### Support

Bug reports and feature requests go in the [Issues tab](https://console.apify.com/actors/PLACEHOLDER/issues). Direct contact: contact@nanoscrape.com. We usually reply within 6 hours.

# Actor input Schema

## `searchQueries` (type: `array`):

One or more search keywords (e.g. 'lecturer in computer science', 'postdoc chemistry', 'PhD studentship physics'). Each runs as a separate search. Results are deduplicated across queries.

## `location` (type: `string`):

UK city or region to filter jobs by (e.g. 'London', 'Manchester', 'Cambridge', 'Edinburgh'). Applied to all search queries.

## `searchUrls` (type: `array`):

Paste one or more Jobs.ac.uk search URLs. Go to jobs.ac.uk, search for academic vacancies, and copy the URL. Keywords and location filters are preserved automatically. Mutually exclusive with searchQueries.

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

Alias of searchUrls — direct SERP URLs to crawl instead of building from keywords. Mutually exclusive with searchQueries.

## `includeJobDetails` (type: `boolean`):

Fetch each job's detail page for the full description, structured salary, employment type, closing date, and any additional PDP-only fields. Otherwise only SERP-visible fields are returned.

## `includeCompanyDetails` (type: `boolean`):

Also fetch each unique employer's company profile page for the About-us text, phone, address, website, and a list of the employer's other currently-open roles. Deduplicated per employer within a run. Adds one HTTP hop per unique employer.

## `maxResults` (type: `integer`):

Total cap across all queries and search URLs.

## `maxResultsPerQuery` (type: `integer`):

Maximum results per search URL or keyword.

## `mode` (type: `string`):

Fast mode extracts basic data from search results. Full mode also fetches each vacancy's detail page for full description, structured salary, contract type, hours, closing date, and PhD studentship extras.

## `maxConcurrency` (type: `integer`):

Maximum number of concurrent detail page requests (full mode only).

## Actor input object example

```json
{
  "location": "London",
  "searchUrls": [
    "https://www.jobs.ac.uk/search/?keywords=lecturer+computer+science&location=London"
  ],
  "includeJobDetails": false,
  "includeCompanyDetails": false,
  "maxResults": 5,
  "maxResultsPerQuery": 5,
  "mode": "fast",
  "maxConcurrency": 5
}
```

# Actor output Schema

## `jobListings` (type: `string`):

Dataset of UK academic vacancies. Each record includes: job id, title, employer name, department, salary (min/max/currency/period/text), contract type, hours, description, employment type, location, country (GB), application URL, source URL, posted/closing dates, position type, academic rank, research field, funding source, and PhD studentship extras (stipend, duration, supervisor).

# 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 = {
    "searchUrls": [
        "https://www.jobs.ac.uk/search/?keywords=lecturer+computer+science&location=London"
    ],
    "maxResults": 5,
    "maxResultsPerQuery": 5,
    "mode": "fast",
    "maxConcurrency": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("santamaria-automations/jobs-ac-uk-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 = {
    "searchUrls": ["https://www.jobs.ac.uk/search/?keywords=lecturer+computer+science&location=London"],
    "maxResults": 5,
    "maxResultsPerQuery": 5,
    "mode": "fast",
    "maxConcurrency": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("santamaria-automations/jobs-ac-uk-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 '{
  "searchUrls": [
    "https://www.jobs.ac.uk/search/?keywords=lecturer+computer+science&location=London"
  ],
  "maxResults": 5,
  "maxResultsPerQuery": 5,
  "mode": "fast",
  "maxConcurrency": 5
}' |
apify call santamaria-automations/jobs-ac-uk-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,santamaria-automations/jobs-ac-uk-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/hG7AFkLM6jCIO7lOG/builds/A5xsJciNH8kSZtKfg/openapi.json
