# UK Police Street-Level Crime Data Scraper (`devilscrapes/uk-police-crime-data-scraper`) Actor

Export UK Police street-level crime records for up to 5 points and a 6-month window: category, month, street name, coordinates, outcome status, and crime id. Keyless data.police.uk API, no auth, no proxy needed.

- **URL**: https://apify.com/devilscrapes/uk-police-crime-data-scraper.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

<div align="center">
  <img src=".actor/icon.svg" width="160" alt="Devil Scrapes mark" />

## UK Police Street-Level Crime Data Scraper

**💰 $2.70 / 1 000 results**  ·  pay only for results  ·  no credit card to try

*The devil's in the data — we just flatten it for you.* 😈

Export UK Police street-level crime records for up to 5 points and a 6-month window: category, month, street name, coordinates, outcome status, and crime id. Keyless data.police.uk API, no auth, no proxy needed.

</div>

***

> **Quick answer:** The **UK Police Street-Level Crime Data Scraper** exports UK Police street-level crime records — category, month, street name, coordinates, outcome status, and crime id — for up to 5 points and a bounded 6-month range, from the public `data.police.uk` API. Pricing is pay-per-result — **$2.70 per 1 000 rows**, no subscription, no card required to try it.

### 🎯 What this scrapes

`data.police.uk` is the UK government's keyless street-level crime API, but a single request downloads an entire month's raw crime file for a point before you can filter it. This Actor queries the public API for up to 5 points and a bounded month range, trims every record to a flat lead-ready row — category, month, street name, coordinates, outcome status, crime id — and stops once your result cap is reached. No API key, no login, no raw-payload cleanup.

### 🔥 What we handle for you

- 🔁 **Retries with exponential backoff** on `408`/`429`/`5xx` and network errors — up to 5 attempts, `Retry-After` honoured.
- 🧊 **Clean, typed dataset rows** — Pydantic-validated, no raw nested payload, `outcome_status` and `persistent_id` normalised to `null` when empty.
- 🧱 **404s handled correctly** — a month too recent to be published yet returns zero rows for that pair, not a failed run.
- 💰 **Pay-Per-Event pricing** — you only pay for rows that land in your dataset. No data, no charge.

### 💡 Use cases

- Real-estate risk screening — pull crime density around a shortlist of addresses before you list or buy.
- Insurance underwriting — attach a crime-context signal to a property or postcode.
- Local journalism and research — track category-level crime trends for a neighbourhood over a bounded month range.
- Neighbourhood/relocation apps — surface recent crime categories near a point of interest.

### ⚙️ How to use it

1. Click **Try for free** at the top of the page.
2. Fill in the input form — most fields have sensible defaults.
3. Click **Start**. Output streams into the run's dataset.
4. Export from **Storage → Dataset** as JSON, CSV, or Excel — or fetch via the API.

### 📥 Input

| Field | Type | Required | Default | Notes |
|---|---|:--:|---|---|
| `locations` | `array` | no | `[{"lat": 51.5074, "lng": -0.1278}]` | 1-5 points; each becomes one lookup in the API's fixed ~1-mile radius. |
| `category` | `string` | no | `"all-crime"` | One of the 15 UK Police crime categories. `all-crime` returns every category. |
| `month_from` | `string` | no | `"2026-06"` | First month (inclusive), `YYYY-MM`. The API lags 1-2 months behind the calendar date. |
| `month_to` | `string` | no | `"2026-06"` | Last month (inclusive), `YYYY-MM`. Must be on/after `month_from`; span capped at 6 months. |
| `max_results` | `integer` | no | `500` | Hard cap on rows emitted. Each (point, month) pair still downloads the full month first. |

#### Example input

```json
{
  "locations": [{ "lat": 51.5074, "lng": -0.1278 }],
  "category": "all-crime",
  "month_from": "2026-06",
  "month_to": "2026-06",
  "max_results": 500
}
```

### 📤 Output

| Field | Type | Notes |
|---|---|---|
| `category` | `string` | Crime category, e.g. `burglary`. |
| `month` | `string` | `YYYY-MM` the crime was recorded. |
| `street_name` | `string` | Nearest street name reported by the API. |
| `latitude` | `float` | Latitude of the reported location. |
| `longitude` | `float` | Longitude of the reported location. |
| `outcome_status` | `string \| null` | Outcome category, or `null` if unresolved. |
| `persistent_id` | `string \| null` | Persistent crime ID, or `null` when the API returns an empty string. |
| `crime_id` | `integer` | Numeric crime ID from the API. |
| `search_lat` | `float` | Latitude of the input point that produced this row. |
| `search_lng` | `float` | Longitude of the input point that produced this row. |

#### Example output

```json
{
  "category": "anti-social-behaviour",
  "month": "2026-06",
  "street_name": "On or near Bedford Street",
  "latitude": 51.510389,
  "longitude": -0.124157,
  "outcome_status": null,
  "persistent_id": null,
  "crime_id": 136061732,
  "search_lat": 51.5074,
  "search_lng": -0.1278
}
```

### 💰 Pricing

Pay-Per-Event — you only pay for what lands in your dataset.

| Event | Price | Trigger |
|---|---|---|
| Actor start | $0.20 | Once per run, after input validation passes. |
| Result row | $0.0025 | Per crime record pushed to the dataset. |

Effective **~$2.70 per 1 000 rows**. A default run (500 rows) costs about $1.45.

### 🚧 Limitations

- Bounded lookup tool: up to 5 points and a 6-month span per run, not an unbounded national or historical mirror.
- The API's ~1-mile search radius is fixed server-side and not configurable.
- The upstream API lags 1-2 months behind the calendar date; very recent months return zero rows for that pair rather than an error.
- No polygon-vertex search and no per-crime-id lookup in v1.

### ❓ FAQ

**Does this need an API key or proxy?**
No. `data.police.uk` is a keyless UK government API with no observed anti-bot behaviour, so this Actor makes direct requests — no `proxyConfiguration` to configure.

**Why did my run return zero rows?**
Either the point/month pair genuinely had no recorded crimes, or the month is too recent for the API's publish lag. Both cases finish as a successful run with a status message explaining what was searched — never a failed run.

**Can I search more than 5 points or a longer date range?**
Not in v1 — this Actor is intentionally bounded to keep runs fast and predictably priced. Contact us if you need a wider range.

**Where does the data come from?**
The UK Police public Street-Level Crimes API (`data.police.uk`), the same open dataset published by UK police forces.

### 📮 Your feedback

Found a bug, a category mismatch, or want a feature? Open an issue on the Actor's Apify Store page or reach out at [apify.com/DevilScrapes](https://apify.com/DevilScrapes) — we read every message.

# Actor input Schema

## `locations` (type: `array`):

1-5 points to search. Each point becomes one lookup in the API's fixed ~1-mile radius, e.g. <code>{"lat": 51.5074, "lng": -0.1278}</code>.

## `category` (type: `string`):

Crime category filter. <code>all-crime</code> returns every category for the point/month.

## `month_from` (type: `string`):

First month (inclusive) to fetch, e.g. <code>2026-06</code>. The API lags 1-2 months behind the calendar date.

## `month_to` (type: `string`):

Last month (inclusive) to fetch, e.g. <code>2026-06</code>. Must be on/after <code>month\_from</code>, span capped at 6 months inclusive.

## `max_results` (type: `integer`):

Hard cap on the number of crime rows emitted by this run. Fetching per (location, month) pair still downloads the full month before this cap is applied.

## Actor input object example

```json
{
  "locations": [
    {
      "lat": 51.5074,
      "lng": -0.1278
    }
  ],
  "category": "all-crime",
  "month_from": "2026-06",
  "month_to": "2026-06",
  "max_results": 500
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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 = {
    "locations": [
        {
            "lat": 51.5074,
            "lng": -0.1278
        }
    ],
    "category": "all-crime",
    "month_from": "2026-06",
    "month_to": "2026-06",
    "max_results": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/uk-police-crime-data-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 = {
    "locations": [{
            "lat": 51.5074,
            "lng": -0.1278,
        }],
    "category": "all-crime",
    "month_from": "2026-06",
    "month_to": "2026-06",
    "max_results": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/uk-police-crime-data-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 '{
  "locations": [
    {
      "lat": 51.5074,
      "lng": -0.1278
    }
  ],
  "category": "all-crime",
  "month_from": "2026-06",
  "month_to": "2026-06",
  "max_results": 500
}' |
apify call devilscrapes/uk-police-crime-data-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,devilscrapes/uk-police-crime-data-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/tDw04WgIUIDKXgtaO/builds/qcUcHHbQYUdfZ5T9n/openapi.json
