# RailwayPeople Jobs Scraper: UK Rail Vacancies by Role & Salary (`getascraper/railwaypeople-jobs-scraper`) Actor

Scrape current UK rail vacancies from RailwayPeople.com's own ~50-category discipline taxonomy: Signalling, Rolling Stock, Overhead Line Engineering, and more. Returns full description, employer, location, dates, employment type, and salary when published. $1.50 per 1,000 jobs.

- **URL**: https://apify.com/getascraper/railwaypeople-jobs-scraper.md
- **Developed by:** [GetAScraper](https://apify.com/getascraper) (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.12 / 1,000 job postings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## 🚆 RailwayPeople Jobs Scraper: UK Rail Vacancies by Role & Salary

<table width="100%">
<tr>
<td style="padding:24px 28px;background:#EDF5F1;border:1px solid #BFDCC9;border-top:4px solid #1F4E42;border-radius:12px">
<span style="font-size:23px;font-weight:800;color:#1C1917;line-height:1.3">Every current UK rail vacancy, structured and ready to use</span><br>
<span style="font-size:15px;color:#57534E;line-height:1.6">Collect job titles, full descriptions, employers, rail disciplines, contract types, dates, and salary when it is published, straight from RailwayPeople.com, the UK's dedicated rail industry job board.</span>
</td>
</tr>
</table>

<table width="100%">
<tr>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #BFDCC9;border-radius:10px 0 0 10px;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#1F4E42">📄 Full job detail</span><br>
<span style="font-size:12px;color:#57534E">Complete description, employer, dates, and salary from every posting</span>
</td>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #BFDCC9;border-left:none;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#1F4E42">🛤️ Real discipline filters</span><br>
<span style="font-size:12px;color:#57534E">Signalling, civil engineering, rolling stock, rail operations, and the board's full category list</span>
</td>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #BFDCC9;border-left:none;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#1F4E42">📍 Multi-site roles handled</span><br>
<span style="font-size:12px;color:#57534E">Every location a vacancy is advertised under, not just the first one listed</span>
</td>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #BFDCC9;border-left:none;border-radius:0 10px 10px 0;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#1F4E42">🔓 No login needed</span><br>
<span style="font-size:12px;color:#57534E">Reads only the public job board. No account, API key, or candidate database access</span>
</td>
</tr>
</table>

RailwayPeople Jobs Scraper collects current public vacancies from railwaypeople.com, the UK rail sector's own dedicated job board since 2001. Use it for recruitment sourcing, salary and hiring benchmarking, or building a rail-specific feed that general job boards do not carry.

### 🔍 What can you collect?

- Job title, direct source link, posting date, and closing date.
- Full job description, in plain text.
- Employer name, profile link, and logo when published.
- Rail discipline category, such as Signalling, Civil Engineering, Rolling Stock, or Rail Operations.
- Employment type (Full Time, Permanent, Contract, Temporary, and more) and work arrangement.
- Location, including every site a multi-location role is advertised under.
- Salary minimum, maximum, currency, and pay period, when the employer has published one.

Missing optional values, such as salary on postings that do not publish one, are left out rather than filled with a placeholder.

### 🎯 Who uses this data?

- **I am a rail sector recruiter** sourcing candidates for signalling, civils, or rolling stock roles without clicking through every listing by hand.
- **I am an HR lead at a rail infrastructure or engineering firm** benchmarking salaries and hiring volume against the rest of the sector before posting a role.
- **I am a market researcher** tracking UK rail industry hiring trends over time.
- **I am a job-data product manager** adding rail-specific vacancies to a feed that general job boards do not cover.

### 🚀 How it works

<table width="100%" style="display:table;width:100%;border-collapse:collapse">
<tr>
<td style="padding:16px 14px;width:33%;background:#EDF5F1;border:1px solid #BFDCC9;border-radius:10px 0 0 10px;vertical-align:top"><span style="font-size:12px;font-weight:800;color:#1F4E42;letter-spacing:1px">STEP 1</span><br><span style="font-size:14px;font-weight:700;color:#1C1917">Set your filters</span><br><span style="font-size:12px;color:#57534E">Keyword, discipline category, contract type, work arrangement. Leave them blank to pull the current listing.</span></td>
<td style="padding:16px 14px;width:33%;background:#EDF5F1;border:1px solid #BFDCC9;border-left:none;vertical-align:top"><span style="font-size:12px;font-weight:800;color:#1F4E42;letter-spacing:1px">STEP 2</span><br><span style="font-size:14px;font-weight:700;color:#1C1917">Run the Actor</span><br><span style="font-size:12px;color:#57534E">It reads the board's own search results, then opens each job for the full posting.</span></td>
<td style="padding:16px 14px;width:33%;background:#EDF5F1;border:1px solid #BFDCC9;border-left:none;border-radius:0 10px 10px 0;vertical-align:top"><span style="font-size:12px;font-weight:800;color:#1F4E42;letter-spacing:1px">STEP 3</span><br><span style="font-size:14px;font-weight:700;color:#1C1917">Use the results</span><br><span style="font-size:12px;color:#57534E">Export the dataset, or schedule the Actor for a recurring hiring feed.</span></td>
</tr>
</table>

Every saved job requires its own detail page request, since the full description, contract type, and precise salary live there rather than on the search results page. RailwayPeople's own `robots.txt` asks for a short gap between requests, so a larger `maxItems` takes proportionally longer to finish.

### 📋 Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `keywords` | string | No | Free-text search term, such as `Signalling` or `Project Manager`. Leave blank to pull the current listing instead of a keyword match. |
| `jobCategories` | array of enum | No | Limit results to one or more rail discipline categories, taken from the board's own taxonomy. Leave empty to include every category. |
| `employmentTypes` | array of enum | No | Limit results to one or more contract types: Full Time, Permanent, Contract, Contract or Permanent, Temporary, Fixed Term Contract, Zero Hours Contract. |
| `workArrangement` | array of enum | No | Limit results to In Person or Hybrid roles. Leave empty to include both. |
| `maxItems` | integer | No | Maximum number of job postings to collect in this run. |
| `proxyConfiguration` | object | No | Apify's datacenter proxy is used by default and is reliable for this source. Residential proxies are not required. |

### 📤 Output example

Each saved item represents one genuine RailwayPeople vacancy.

```json
{
    "jobId": "58440",
    "url": "https://www.railwaypeople.com/job/olec-3-engineers-58440",
    "title": "OLEC 3 Engineers",
    "description": "OLEC 3 - Contract Opportunity\nLocation: Old Oak Common\n...",
    "category": "Overhead Line Engineering",
    "categoryId": "542",
    "employmentType": "FULL_TIME",
    "directApply": true,
    "applicationWorkflow": "internal",
    "isFeatured": false,
    "isTopJob": true,
    "datePosted": "2026-09-25T14:10:47+01:00",
    "validThrough": "2026-10-23T14:10:47+01:00",
    "organizationName": "Ganymede",
    "organizationUrl": "https://www.railwaypeople.com/organization/ganymede",
    "organizationLogoUrl": "https://www.railwaypeople.com/sites/default/files/styles/job_squared_logo_medium/public/org_logos/example.png",
    "location": "London Borough of Ealing, UK",
    "scrapedAt": "2026-10-01T10:19:49.800Z"
}
```

### 📊 Data table

| Field | Type | Description |
| --- | --- | --- |
| `jobId` | string | RailwayPeople's own internal job identifier. |
| `url` | string | Direct link to the public job posting. |
| `title` | string | Published job title. |
| `description` | string | Full published description, in plain text. |
| `category` | string | Primary rail discipline category. |
| `categoryId` | string | The board's own identifier for that category. |
| `additionalCategories` | array | Any further categories the job is also tagged with. |
| `employmentType` | string | Published employment type, such as `FULL_TIME` or `CONTRACTOR`. |
| `workArrangement` | string | Published work arrangement, such as In Person or Hybrid, when stated. |
| `directApply` | boolean | Whether the posting supports applying directly through RailwayPeople. |
| `applicationWorkflow` | string | How the application is routed by the board. |
| `isFeatured` | boolean | Whether RailwayPeople marks the listing as featured. |
| `isTopJob` | boolean | Whether RailwayPeople marks the listing as a top job. |
| `datePosted` | string | Publication date. |
| `validThrough` | string | Closing date, when published. |
| `organizationName` | string | Employer name. |
| `organizationUrl` | string | Employer's RailwayPeople profile link. |
| `organizationLogoUrl` | string | Employer logo, when published. |
| `location` | string | Primary advertised location. |
| `additionalLocations` | array | Any further locations the role is advertised under. |
| `salaryMin` | number | Minimum published salary, when the employer provides one. |
| `salaryMax` | number | Maximum published salary, when the employer provides one. |
| `salaryCurrency` | string | Published salary currency. |
| `salaryUnit` | string | Published salary period, such as `YEAR`. |
| `scrapedAt` | string | Time the job was collected. |

### 🗂️ Output

- **🚆 Job Listings:** The primary overview, with title, employer, category, employment type, location, and dates.
- **📍 Location & Salary:** Every advertised location alongside published salary details.

### 💰 Pricing

Pricing is pay per result: $1.50 per 1,000 jobs. You are not charged for empty runs. There is no fixed subscription.

Free-plan runs are limited to 25 jobs per run, 3 runs per day, and a short wait between runs.

### ⭐ Enjoying RailwayPeople Jobs Scraper?

<table width="100%" style="display:table;width:100%">
<tr>
<td style="padding:20px 24px 14px;background:#EDF5F1;border:1px solid #BFDCC9;border-left:5px solid #1F4E42;border-radius:10px 10px 0 0"><span style="font-size:20px;letter-spacing:4px;color:#1C1917">⭐ ⭐ ⭐ ⭐ ⭐</span><br><span style="font-size:17px;font-weight:800;color:#1C1917">Spend less time clicking through listings and more time using UK rail hiring data.</span><br><span style="font-size:14px;color:#57534E">A rating takes a few seconds and helps other recruiters and researchers find this Actor. Your feedback also guides future improvements.</span></td>
</tr>
<tr>
<td style="padding:0;background:#1F4E42;border:1px solid #BFDCC9;border-top:none;border-radius:0 0 10px 10px;text-align:center"><a href="https://apify.com/getascraper/railwaypeople-jobs-scraper/reviews" style="display:block;padding:13px 16px;color:#FFFFFF;text-decoration:none;font-weight:800;font-size:15px;letter-spacing:0.3px">★&nbsp;&nbsp;Rate this Actor on Apify</a></td>
</tr>
</table>

### ❓ FAQ

##### Does this cover every rail job in the UK?

No. It covers what is currently published on RailwayPeople.com, a dedicated rail industry board with roughly 100 to 270 live postings at any time. It does not aggregate from other job boards.

##### Can I filter to a specific discipline, like signalling or civils?

Yes. Use `jobCategories` with the board's own category list, which covers engineering disciplines, construction, operations, and support roles across the rail sector.

##### How fresh is the data?

Each run reads whatever is live on the board at that moment. Schedule the Actor on Apify for a recurring hiring feed.

##### What happens when a field is not published, like salary?

It is left out of that job's record rather than filled with a placeholder. Most postings on this board do not publish a salary.

### 🛟 Support and responsible use

This Actor collects public job-posting data and is not affiliated with RailwayPeople.com. Follow applicable terms, privacy rules, and local laws when using the results.

If a run does not match what you expect, open the **Issues** tab and share the run link.

### 🔗 Other actors

- [CWJobs Scraper: UK tech jobs, salaries & employers](https://apify.com/getascraper/cwjobs-scraper) ↗ - Collect UK technology vacancies, salaries, and employer details.
- [TargetJobs UK scraper: graduate jobs, schemes, and internships](https://apify.com/getascraper/targetjobs-uk-scraper) ↗ - Track UK graduate schemes and internships.
- [S1 Jobs Scraper: Scotland Jobs, Salaries & Employers](https://apify.com/getascraper/s1jobs-scraper) ↗ - Collect Scotland vacancies, salaries, and employer details.
- [EURAXESS Jobs Scraper: research vacancies that stay current](https://apify.com/getascraper/euraxess-jobs-scraper) ↗ - Track European research and engineering vacancies.
- [Workday jobs scraper](https://apify.com/getascraper/workday-tenant-jobs-monitor) ↗ - Monitor vacancies published on any public Workday careers site.

# Changelog

This Actor's version history is a separate document: https://apify.com/getascraper/railwaypeople-jobs-scraper/changelog.md

# Actor input Schema

## `keywords` (type: `string`):

Free-text search term sent to RailwayPeople's own job search, for example "Signalling" or "Project Manager". Leave blank to pull the full current listing instead of a keyword match.

## `jobCategories` (type: `array`):

Limit results to one or more rail discipline categories, taken from RailwayPeople's own category taxonomy. Leave empty to include every category.

## `employmentTypes` (type: `array`):

Limit results to one or more contract types, taken from RailwayPeople's own filters. Leave empty to include every employment type.

## `workArrangement` (type: `array`):

Limit results by where the role is performed. Leave empty to include both in-person and hybrid roles.

## `maxItems` (type: `integer`):

Maximum number of job postings to collect. Each job always requires its own detail-page fetch to get the full description, since RailwayPeople's own robots.txt asks for a 10-second gap between requests, so a larger value takes proportionally longer to run.

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

RailwayPeople's job pages are plain server-rendered HTML with no anti-bot tier observed during testing, so Apify's datacenter proxy group works reliably. Residential proxies are not required.

## Actor input object example

```json
{
  "keywords": "",
  "jobCategories": [],
  "employmentTypes": [],
  "workArrangement": [],
  "maxItems": 15,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "keywords": "",
    "jobCategories": [],
    "employmentTypes": [],
    "workArrangement": [],
    "maxItems": 15,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("getascraper/railwaypeople-jobs-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 = {
    "keywords": "",
    "jobCategories": [],
    "employmentTypes": [],
    "workArrangement": [],
    "maxItems": 15,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("getascraper/railwaypeople-jobs-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 '{
  "keywords": "",
  "jobCategories": [],
  "employmentTypes": [],
  "workArrangement": [],
  "maxItems": 15,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call getascraper/railwaypeople-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,getascraper/railwaypeople-jobs-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/B4KO8kMZchK6vonlz/builds/E2hGG0YVtu3ukpSF7/openapi.json
