# RPKI Relying-Party VRP Extractor (`datamule/rpki-vrp-extractor`) Actor

Point at ANY RPKI validator's VRP export (rpki-client, Routinator, FORT, Cloudflare) and extract validated ROAs: origin ASN, prefix, maxLength, trust anchor, expiry. Optional ASN / prefix / trust-anchor filters. Auto-detects the array key. Seeded on Cloudflare & rpki-client.org.

- **URL**: https://apify.com/datamule/rpki-vrp-extractor.md
- **Developed by:** [Datamule](https://apify.com/datamule) (community)
- **Categories:** Developer tools, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.28 / 1,000 validated roas

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/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

## RPKI Relying-Party VRP Extractor

Point at **any RPKI validator's VRP export** and extract every validated ROA —
**origin ASN, prefix, maxLength, trust anchor, and expiry** — with optional
ASN / prefix / trust-anchor filters.

Every RPKI **Relying-Party** validator (rpki-client, Routinator, FORT,
OctoRPKI / Cloudflare) publishes the ROAs it validated from the five RIR trust
anchors (AFRINIC, APNIC, ARIN, LACNIC, RIPE) as a JSON dump — the
**Validated ROA Payload (VRP)** set. Incumbents scrape RIPEstat / PeeringDB
*around* routing security; this actor parses the VRP set itself, generically,
so one actor reads any validator that publishes a dump.

Verified live against **Cloudflare** (`https://rpki.cloudflare.com/rpki.json`,
\~973k ROAs) and **rpki-client.org**
(`https://console.rpki-client.org/vrps.json`, ~973k ROAs).

### What you get

One normalized row per validated ROA, plus one trailing metadata record:

| Field | Description |
|-------|-------------|
| `asn` | Origin ASN, normalized to `AS<n>` (accepts `13335` or `"AS13335"` at source) |
| `_asnNum` | The numeric AS number, for range / equality ops |
| `prefix` | The authorized IP prefix (CIDR) |
| `_prefixLen` | The prefix length (`/N`), derived |
| `maxLength` | ROA maxLength (nullable) |
| `ta` | Trust anchor: `afrinic` / `apnic` / `arin` / `lacnic` / `ripe` (nullable) |
| `expires` | Expiry as Unix epoch (nullable — some validators omit it) |
| `expiresIso` | Expiry as an ISO-8601 UTC string (nullable) |
| `_source` | The export host |
| `_recordType` | `roa` for ROA rows, `meta` for the trailing metadata record |
| `_meta` | On the metadata record only: the validator's own buildtime / elapsedtime / vrps count + the emitted-row count + the filters used |

### Input

| Field | Required | Description |
|-------|----------|-------------|
| `vrpUrl` | ✅ | Validator VRP export URL, e.g. `https://rpki.cloudflare.com/rpki.json` |
| `filterAsn` | | Keep only ROAs for this origin ASN (`AS13335` or `13335`) |
| `filterPrefix` | | Keep only ROAs whose prefix is within this CIDR (e.g. `1.0.0.0/8`) |
| `ta` | | Keep only ROAs from this trust anchor (`afrinic` / `apnic` / `arin` / `lacnic` / `ripe`) |
| `maxRecords` | | Stop after N ROAs (default 50000; raise to pull the full ~1M set) |

### Example

```json
{
  "vrpUrl": "https://console.rpki-client.org/vrps.json",
  "filterAsn": "AS13335",
  "maxRecords": 5000
}
```

### Use cases

- **BGP Route-Origin-Validation (ROV)** — the authoritative allow-list of which
  ASNs may originate which prefixes, to check announcements against.
- **RIR / RPKI compliance audit** — which of your prefixes have valid ROAs, per
  trust anchor, and when they expire.
- **IRR / routing-hygiene tooling** — cross-check IRR objects against the
  validated ROA set.
- **Network-intelligence & threat research** — a normalized, filterable feed of
  the global VRP set from any validator.

### How it works

- Sends a browser-ish User-Agent + `Accept: application/json` and follows
  redirects.
- Reads the **full** ~100 MB body before parsing (a truncated read is a parse
  failure, not fewer rows).
- **Auto-detects the VRP array key** (`roas` → `vrps` → `data` → a bare root
  list) so it reads any validator's dump shape.
- Normalizes the inconsistently-typed `asn` (`13335` vs `"AS13335"`) to a
  canonical `AS<n>` + numeric `_asnNum`, and treats every field except `asn`
  and `prefix` as nullable.
- **Fails fast — never a fabricated empty success** — if the URL is
  unreachable, serves HTML / 403 instead of JSON, returns no recognizable VRP
  array, or matches zero ROAs.

### Pricing

Pay-per-event: **$0.0004 per record** (tiered volume discount by subscription
tier). You pay only for ROAs actually emitted; the trailing metadata record is
free.

# Actor input Schema

## `vrpUrl` (type: `string`):

URL of ANY RPKI validator's VRP (Validated ROA Payload) JSON export. Every Relying-Party validator (rpki-client, Routinator, FORT, OctoRPKI / Cloudflare) publishes the ROAs it validated from the five RIR trust anchors. Verified live: https://rpki.cloudflare.com/rpki.json (Cloudflare, ~973k ROAs) and https://console.rpki-client.org/vrps.json (rpki-client.org, ~973k ROAs). The actor auto-detects the array key (roas / vrps / data / bare list) so it reads any validator that publishes a VRP dump. A URL that returns HTML / 403 / a non-array body fails fast (never emits empty).

## `filterAsn` (type: `string`):

Keep only ROAs authorizing this origin ASN. Accepts either 'AS13335' or '13335'. Leave empty to keep every ASN.

## `filterPrefix` (type: `string`):

Keep only ROAs whose prefix is contained within this CIDR (proper subnet containment when both parse as networks, e.g. '1.0.0.0/8' matches '1.0.0.0/24'; otherwise a substring match). Leave empty to keep every prefix.

## `ta` (type: `string`):

Keep only ROAs derived from this RIR trust anchor. Leave empty for all five.

## `maxRecords` (type: `integer`):

Stop after emitting this many ROAs. VRP dumps are ~1M rows; the default caps generously but you can raise it to pull the full set. Each emitted ROA is billed as one record; the trailing metadata record is not billed.

## `userAgent` (type: `string`):

Override the default browser-ish User-Agent header. Some validators require a real UA + redirect follow to serve the export.

## `timeoutSecs` (type: `integer`):

Per-request timeout in seconds for the VRP fetch. The dumps are ~100 MB, so keep this generous (default 120).

## Actor input object example

```json
{
  "vrpUrl": "https://rpki.cloudflare.com/rpki.json",
  "filterAsn": "AS13335",
  "filterPrefix": "1.0.0.0/8",
  "ta": "",
  "maxRecords": 50000,
  "timeoutSecs": 120
}
```

# 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 = {
    "vrpUrl": "https://console.rpki-client.org/vrps.json"
};

// Run the Actor and wait for it to finish
const run = await client.actor("datamule/rpki-vrp-extractor").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 = { "vrpUrl": "https://console.rpki-client.org/vrps.json" }

# Run the Actor and wait for it to finish
run = client.actor("datamule/rpki-vrp-extractor").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 '{
  "vrpUrl": "https://console.rpki-client.org/vrps.json"
}' |
apify call datamule/rpki-vrp-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datamule/rpki-vrp-extractor"
        }
    }
}

```

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/n2OoXJXRIf6J4TC4t/builds/dWLf63BZObq4uFg7j/openapi.json
