# Hansard Parliamentary Debates (`spookyweb/uk-hansard-parliamentary-debates`) Actor

Every contribution from the House of Commons and Lords via the official Hansard API. Speaker, party, constituency, full text and timestamps, ideal for political research and AI training data.

- **URL**: https://apify.com/spookyweb/uk-hansard-parliamentary-debates.md
- **Developed by:** [丂卩ㄖㄖҜㄚ](https://apify.com/spookyweb) (community)
- **Categories:** News, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 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/platform/actors/running/actors-in-store#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

## UK Hansard Parliamentary Debates

Extract full text UK parliamentary debates from the official Hansard record: one row per contribution, with the speaker, party, constituency, debate title, timestamp and the text itself.

### 🔍 What does UK Hansard Parliamentary Debates do?

It walks the official Hansard record for a date range and returns every contribution as a clean row of data, ready for a corpus, a RAG index, a database or your own product.

It covers:

- House of Commons debates
- House of Lords debates
- Westminster Hall debates
- Written ministerial statements

Weekends are skipped automatically, and days when the House did not sit return nothing.

### 📊 What data can I extract from Hansard?

One row per contribution:

| Field | Description |
|---|---|
| `date` | Sitting date, YYYY-MM-DD |
| `house` | Commons or Lords |
| `section` | Debate, WestHall or WMS |
| `debateTitle` | Title of the debate or question |
| `debateId` | Hansard debate identifier |
| `speaker` | Member name, null for unattributed text |
| `role` | Ministerial role or Chair, where the attribution carries one |
| `constituency` | Seat, Commons members only |
| `party` | Party abbreviation, for example Lab or Con |
| `memberId` | Parliament member id, useful for joining to other datasets |
| `time` | Timestamp of the contribution where Hansard records one |
| `text` | Full contribution text, markup stripped |
| `wordCount` | Word count |
| `uin` | Unique identifying number for written questions |
| `contributionId` | Hansard contribution identifier |
| `url` | Link to the debate on Hansard |

### 💡 Why use Hansard data?

**LLM training and fine-tuning.** Millions of words of formal political discourse, already attributed to a named speaker and party.

**RAG and search.** Build a parliamentary knowledge base you can cite, with a source URL on every row.

**Policy and legislative research.** Track how a bill or a topic was argued over time, and by whom.

**Fact checking and media.** Verify a quote against the official record rather than a press report of it.

### 🚀 How do I use UK Hansard Parliamentary Debates?

1. Click **Try for free**.
2. Pick a `chamber`: `commons`, `lords` or `both`.
3. Set `startDate` and `endDate` to bound the range, YYYY-MM-DD.
4. Add a `searchTerm` to keep only contributions containing a word or phrase, and set `maxSpeeches` to cap the run.
5. Click **Start**, then download the results as JSON, CSV or Excel, or pull them from the API.

### ⬇️ Input

```json
{
  "chamber": "commons",
  "startDate": "2024-01-01",
  "searchTerm": "housing",
  "maxSpeeches": 5000
}
```

| Field | Type | Default | What it does |
|---|---|---|---|
| `chamber` | string | `commons` | Which house to collect, commons, lords or both |
| `startDate` | string | `2024-01-01` | First sitting date to collect, YYYY-MM-DD |
| `endDate` | string | | Last sitting date, leave empty for today |
| `searchTerm` | string | | Only contributions containing this term |
| `includeWrittenAnswers` | boolean | `true` | Include written ministerial statements, the WMS section |
| `includeWestminsterHall` | boolean | `true` | Include Westminster Hall debates |
| `maxSpeeches` | integer | `5000` | Hard cap on the number of results |

Two more options are worth knowing. `maxDays` limits the run to N weekday dates, where `0` means every weekday in the range. `includeProcedural` adds short non-speech entries such as Prayers and the sitting date, and it is off by default because each one is a billable result.

### ⬆️ Output

#### Table view

Results arrive as a Contributions table you can sort and filter in the Console, with the date, house, debate title, speaker and word count lined up for scanning.

#### JSON

A typical row:

```json
{
  "date": "2026-06-03",
  "house": "Commons",
  "section": "Debate",
  "debateTitle": "Supreme Court Dillon Judgment: Policy Implications",
  "debateId": "C66E1F5D-9FA8-409F-9D3B-87F3A026A61A",
  "speaker": "Peter Swallow",
  "role": null,
  "constituency": "Bracknell",
  "party": "Lab",
  "memberId": 5182,
  "time": "11:32:00",
  "text": "What assessment he has made of the potential implications...",
  "wordCount": 26,
  "uin": null,
  "contributionId": "26060368000025",
  "url": "https://hansard.parliament.uk/commons/2026-06-03/debates/C66E1F5D-9FA8-409F-9D3B-87F3A026A61A"
}
```

Download it from the run as JSON, CSV or Excel, or read it straight from the API.

### Dataset size examples

Typical volume per time period:

| Period | Contributions | Approximate words |
|---|---|---|
| 1 day | 50 to 200 | 50,000 to 200,000 |
| 1 week | 200 to 800 | 200k to 800k |
| 1 month | 1,000 to 3,000 | 1M to 3M |
| 1 year | 12,000 to 35,000 | 12M to 35M |

And for larger corpora:

| Range | Contributions | Approximate words |
|---|---|---|
| Full 2024 | around 25,000 | around 25M |
| Last 5 years | around 125,000 | around 125M |
| Modern era, 2000 onwards | 600,000 plus | 600M plus |

Three runs to size against: 30 days of Commons returns around 5,000 contributions; `climate change` across both houses since 2020 returns around 2,000; a full calendar year across both houses returns around 30,000.

### Recommended update schedule

For an ongoing corpus, run daily at 2am UTC to capture the previous day's debates. Hansard publishes the next working day after a sitting.

For a historical corpus, run once across the full date range and store the output in your own pipeline rather than re-fetching it.

### Proxies and reliability

The Actor uses Apify's residential proxy service to avoid rate limiting and keep access to Hansard reliable. Proxy cost is included in the per-result price, so there is nothing to configure.

### 💰 How much does it cost?

You pay per contribution returned. Set `maxSpeeches` to cap what a run can cost, which matters most when a wide date range would otherwise produce far more rows than you expected.

Days when the House did not sit return nothing and are not charged. Leaving `includeProcedural` off keeps short procedural entries such as Prayers out of the bill. Paid Apify plans get a lower rate per contribution.

### 🔌 Integrations

Send results straight to Google Sheets, Slack, Airtable, Zapier, Make or your own webhook using [Apify integrations](https://docs.apify.com/platform/integrations). You can also trigger a run whenever something happens in another tool, and the Actor is callable from AI agents and MCP clients through the standard Apify API.

### 🔗 Using UK Hansard Parliamentary Debates with the Apify API

```bash
curl -X POST "https://api.apify.com/v2/acts/spookyweb~uk-hansard-parliamentary-debates/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"chamber": "commons", "startDate": "2024-01-01", "searchTerm": "housing", "maxSpeeches": 5000}'
```

Or with the Apify client:

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

const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('spookyweb/uk-hansard-parliamentary-debates').call({
  chamber: 'commons',
  startDate: '2024-01-01',
  searchTerm: 'housing',
  maxSpeeches: 5000,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Full detail is in the [Apify API reference](https://docs.apify.com/api/v2), and every run is also callable from the [Python](https://docs.apify.com/api/client/python) and [JavaScript](https://docs.apify.com/api/client/js) clients.

### ❓ FAQ

#### Does it cover the Lords as well as the Commons?

Yes. Set `chamber` to `lords` for the upper house only, or `both` to collect the two together. The `house` field on every row tells you which one a contribution came from, so a `both` run is easy to split afterwards.

#### Does it include written questions and Westminster Hall?

Yes, and both are on by default. `includeWrittenAnswers` covers written ministerial statements, `includeWestminsterHall` covers Westminster Hall debates. The `section` field labels each row as Debate, WestHall or WMS, so you can filter them apart later. Written parliamentary questions and answers live in a separate Parliament API and are not part of the Hansard debate record.

#### How far back does it go?

The official Hansard record runs back to 1803, and structured coverage through the Hansard API is reliable from 2005 onwards. Set `startDate` to whatever you need and the Actor walks forward from there, skipping weekends and non-sitting days.

#### Can I search for a term across debates?

Yes, `searchTerm` keeps only contributions containing that term. It is the cheapest way to build a topic corpus, because contributions that do not match are never returned and never charged.

#### What counts as one item?

One contribution, meaning a single speech, intervention or written statement, exactly as Hansard segments it. That is also the billing unit. Procedural entries such as Prayers are contributions too, which is why `includeProcedural` is off by default.

#### Do I need a Hansard API key?

No. There is nothing to register for and no quota to manage. Give the Actor a date range and it handles pagination, non-sitting days and rate limiting for you.

### ⚖️ Is it legal to scrape Hansard?

Hansard is the official report of proceedings in Parliament, published under the Open Parliament Licence, which expressly permits reuse, including commercial reuse, subject to acknowledgement. Contributions are made by members in their public role. This Actor uses the official Hansard API.

Source: [hansard.parliament.uk](https://hansard.parliament.uk). Apify's [ethical scraping guide](https://blog.apify.com/is-web-scraping-legal/) covers the wider picture.

### 👍 Your feedback

Found a bug, or want a field that is not here yet? Open an issue on the Actor's Issues tab. Requests that make the data more useful get built, and problems get fixed quickly.

### 🔎 You might also like

| Actor | What it does |
|---|---|
| [UK Case Law Search and Monitor](https://apify.com/spookyweb/uk-case-law-search-monitor) | Court judgments and tribunal decisions from Find Case Law, with full text and change monitoring |
| [UK ICO Enforcement Actions](https://apify.com/spookyweb/uk-ico-enforcement-actions) | ICO fines, reprimands, enforcement notices and prosecutions with fine amounts and sectors |
| [UK Planning Applications](https://apify.com/spookyweb/uk-planning-applications) | Planning applications from every UK council, tagged by the type of work proposed |

# Actor input Schema

## `chamber` (type: `string`):

Which House to take debates from. Use commons for the House of Commons, lords for the House of Lords, or both to return them together in one dataset.

## `startDate` (type: `string`):

Scrape debates from this date onwards (YYYY-MM-DD)

## `endDate` (type: `string`):

Scrape debates until this date (YYYY-MM-DD, leave empty for today)

## `maxDays` (type: `integer`):

Limit the number of weekday dates processed. 0 means every weekday in the range.

## `includeWrittenAnswers` (type: `boolean`):

Include written ministerial statements, the WMS section of Hansard. Written parliamentary questions and answers live in a separate Parliament API and are not covered.

## `includeWestminsterHall` (type: `boolean`):

Include Westminster Hall debates (Commons only)

## `searchTerm` (type: `string`):

Only include debates/speeches mentioning this term

## `maxSpeeches` (type: `integer`):

Hard cap on dataset items. Each contribution is one billable result, so this protects against a wide date range producing a huge charge.

## `includeProcedural` (type: `boolean`):

Include short non-speech entries such as Prayers, the sitting date, and Chair announcements. These are billable results, so they are excluded by default.

## Actor input object example

```json
{
  "chamber": "commons",
  "startDate": "2024-01-08",
  "maxDays": 5,
  "includeWrittenAnswers": true,
  "includeWestminsterHall": true,
  "searchTerm": "",
  "maxSpeeches": 1000,
  "includeProcedural": false
}
```

# Actor output Schema

## `results` (type: `string`):

One row per item: spoken contributions from Hansard.

# 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 = {
    "startDate": "2024-01-08",
    "maxDays": 5,
    "maxSpeeches": 1000
};

// Run the Actor and wait for it to finish
const run = await client.actor("spookyweb/uk-hansard-parliamentary-debates").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 = {
    "startDate": "2024-01-08",
    "maxDays": 5,
    "maxSpeeches": 1000,
}

# Run the Actor and wait for it to finish
run = client.actor("spookyweb/uk-hansard-parliamentary-debates").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 '{
  "startDate": "2024-01-08",
  "maxDays": 5,
  "maxSpeeches": 1000
}' |
apify call spookyweb/uk-hansard-parliamentary-debates --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,spookyweb/uk-hansard-parliamentary-debates"
        }
    }
}

```

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/f3o1HWEJBdA1MdVqC/builds/150zjiv2JSGCXJvbo/openapi.json
