# Ransomware Breach Claim Monitor for SOC Teams (`khadinakbar/ransomware-breach-monitor`) Actor

Monitor public ransomware leak-site claims from RansomLook against an organization and domain watchlist. Returns matched victim claims, group, discovery time, clear-web source links, verification status, and machine-readable run summaries for SOC, CTI, and incident-response workflows.

- **URL**: https://apify.com/khadinakbar/ransomware-breach-monitor.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Developer tools, MCP servers, Automation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 matched ransomware claims

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Ransomware Claim Monitor with Delta Claim IDs

Monitor a watchlist of company names, brands, and domains against public ransomware leak-site claims indexed by [RansomLook](https://www.ransomlook.io/). The Actor returns one compact record per matched claim with the claimed organization, ransomware group, discovery time, match details, a clear-web source link when available, and an explicit `unverified` status.

This is a defensive OSINT monitor for SOC teams, incident responders, CTI analysts, and MSPs. Each row carries an explicit `unverified` label and source provenance so analysts can corroborate a public signal through their authorized response process. The scope is public index metadata: claim titles, groups, timestamps, and safe clear-web source links.

### Scope and best results

- Run a daily or hourly bounded snapshot for your own organization, suppliers, or authorized clients.
- Check exact domains with `matchMode: "strict"` to reduce false positives.
- Add a brand or legal name when a public claim may omit the domain.
- Use `matchMode: "contains"` only when you accept broader name matches and will review them manually.
- Use `groupAllowlist` when a CTI workflow is following specific public group labels.
- Pass previously handled `claimId` values through `excludeClaimIds` when a scheduled run should return only new claims.

Credential exposure, employee email monitoring, and private breach-database work belong in an authorized source and workflow. This Actor's input surface is organization names and domains, and its output surface is public claim metadata for triage.

### Focused standalone workflow

This Actor is designed as a focused standalone workflow for a bounded public-source watchlist snapshot. Feed the default Dataset into an authorized case-management, SIEM, or enrichment process; that downstream system can own notification, corroboration, and retention. Stable `claimId` values provide the handoff key for an incident-response or alerting workflow, and the caller can use them as a stateless baseline for delta-only monitoring.

### Workflow example

An MSP maintains an authorized supplier watchlist and schedules this Actor with a seven-day window. The dataset returns the newest matching claim records first. The MSP routes any `verificationStatus: "unverified"` match into its incident-response process, corroborates it through authorized channels, and stores the `sourceApiUrl`, optional `claimUrl`, `discoveredAt`, and `detectedAt` timestamps with the case. Repeated runs are stateless snapshots, so the downstream system can diff `claimId` values without relying on hidden cross-customer state.

### Output: what one result contains

One dataset item represents one normalized public claim matched to at least one watchlist entry. Multiple matching watchlist values stay in `matchedWatchlistItems`; the Actor does not bill or emit duplicate rows for the same normalized claim.

| Field | Meaning |
| --- | --- |
| `claimId` | Stable hash-based ID for the group, claim title, and discovery timestamp. |
| `victimName` | Organization name as recorded in the public claim title. |
| `groupName` | Ransomware or extortion group associated with the claim. |
| `watchlistItem` / `matchedWatchlistItems` | The watchlist value(s) that matched. |
| `matchType` / `matchStrength` / `matchMode` | Domain or name match, deterministic precision label, and matching policy used. |
| `discoveredAt` | ISO 8601 timestamp reported by RansomLook. |
| `detectedAt` | Timestamp when this Actor observed the source record. |
| `claimAgeHours` | Hours between source discovery and this observation, rounded for triage ordering. |
| `claimUrl` | RansomLook clear-web detail link when the optional recent feed provides one; otherwise `null`. |
| `verificationStatus` | Always `unverified`; incident confirmation belongs to authorized corroboration. |

Example record shape:

```json
{
  "claimId": "ransomlook:6d8e7b2f0b4d1a6a9c12",
  "victimName": "Example Holdings",
  "groupName": "qilin",
  "watchlistItem": "example.com",
  "matchedWatchlistItems": ["example.com", "Example Holdings"],
  "matchType": "domain",
  "matchStrength": "exact_domain",
  "matchMode": "strict",
  "discoveredAt": "source-reported ISO-8601 timestamp",
  "detectedAt": "Actor observation ISO-8601 timestamp",
  "claimAgeHours": 0.5,
  "claimType": "ransomware-leak-site-claim",
  "verificationStatus": "unverified",
  "sourceName": "RansomLook",
  "sourceApiUrl": "https://www.ransomlook.io/api/posts?days=7",
  "claimUrl": "https://www.ransomlook.io/site/blog?uuid=00000000-0000-0000-0000-000000000000",
  "runId": "abc123"
}
```

### Incremental monitoring workflow

- Establish an initial bounded watchlist snapshot and keep the returned `claimId` values in your case-management or alerting system.
- Send those IDs in `excludeClaimIds` on a later run; the Actor suppresses previously handled claims before dataset writes and billing.
- Read `OUTPUT.knownClaimsSkipped` and `RUN_SUMMARY` to keep an auditable count of the baseline claims that were intentionally omitted.

This keeps customer baselines outside the Actor and avoids cross-run or cross-customer state. A zero-row delta run remains `VALID_EMPTY` when the public source was processed successfully.

### Quick start

```json
{
  "watchlist": ["example.com", "Example Holdings"],
  "lookbackDays": 7,
  "maxResults": 25,
  "matchMode": "strict",
  "groupAllowlist": [],
  "excludeClaimIds": []
}
```

The Actor queries the public RansomLook posts feed for the selected window and uses the recent feed only to enrich matching rows with a safe RansomLook detail URL. Source access is limited to the public RansomLook API, and the input surface contains watchlist values rather than secrets.

### Input reference

| Field | Type | Default | Purpose |
| --- | --- | --- | --- |
| `watchlist` | string\[] | required | 1–100 organization names, brands, or domains. Exact duplicate values are removed. |
| `lookbackDays` | integer | `7` | Public source window from 1–30 days. |
| `maxResults` | integer | `25` | Persisted matched-claim cap from 1–500. |
| `matchMode` | enum | `strict` | `strict` uses token-boundary names and exact domains; `contains` broadens names. |
| `groupAllowlist` | string\[] | `[]` | Optional 1–50 public ransomware group labels to include. |
| `excludeClaimIds` | string\[] | `[]` | Optional prior `ransomlook:` IDs to suppress for a stateless new-claim delta. |

### Use through the API

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~ransomware-breach-monitor/runs" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"watchlist":["example.com","Example Holdings"],"lookbackDays":7,"maxResults":25,"matchMode":"strict","groupAllowlist":[],"excludeClaimIds":[]}'
```

Read the run's default Dataset for matched claims. `OUTPUT`, `RUN_SUMMARY`, and `LAST_RUN_SUMMARY` are written to the default Key-Value Store. When the result count reaches `maxResults`, page the Dataset or reduce the window/watchlist for a narrower snapshot.

### Use with an AI agent through Apify MCP

Connect Apify MCP in your client, then ask:

> Check these authorized organization names and domains for new public ransomware leak-site claims from the last 7 days. Limit to Qilin if group labels are available, suppress the claim IDs I already handled, and return victimName, groupName, matchStrength, claimAgeHours, claimUrl, verificationStatus, and the terminal outcome.

The tool reads public source data only; organization-side actions stay with the authorized downstream process. A successful no-match run is `VALID_EMPTY`; a capped or partially enriched run is `PARTIAL`; an unavailable required source is reported as `UPSTREAM_FAILED` with a terminal summary so an agent can route the result deliberately.

### Pricing

Pay per event plus Apify platform usage. Confirm the current event prices on the live Pricing tab if this README ever lags.

- `apify-actor-start`: `$0.00005` per run.
- `matched-claim`: `$0.02` per persisted matched claim.

The maximum event charge for a run with `maxResults: 25` is `$0.50005` before Apify platform usage. A valid empty watchlist window has no `matched-claim` event charges, but platform usage may still apply. The Actor logs its event cap before collection.

### Terminal outcomes

| Outcome | Meaning |
| --- | --- |
| `COMPLETE` | All selected matches were persisted and optional enrichment was available. |
| `PARTIAL` | Useful matches were persisted, with a result cap, charge cap, source-row quality issue, write issue, or optional enrichment gap recorded in the summary. |
| `VALID_EMPTY` | The public source was processed successfully and no claim matched the watchlist. |
| `INVALID_INPUT` | The watchlist or bounds can be corrected by the caller; no match event is charged. |
| `UPSTREAM_FAILED` | The required public RansomLook posts feed was unavailable or matched rows lacked persistence. |
| `CONFIG_ERROR` | The Apify run charge cap allowed no matched claim to be billed; raise `maxTotalChargeUsd` and retry. |

### Source, freshness, and data-quality guidance

RansomLook documents its public API at [ransomlook.io/doc](https://www.ransomlook.io/doc/) and describes its content as open-source intelligence. It states that API responses and datasets are available under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/); this Actor attributes the source in every row and in this README. Respect the source's current terms and fair-use expectations.

The source reports public claims collected from ransomware leak sites. A claim may be wrong, duplicated, stale, rebranded, or attributed to the wrong organization. RansomLook's `discovered` value is the source-reported discovery time; incident-date confirmation belongs to your authorized IR, legal, and communications processes. A snapshot with zero matches means that this public index supplied no signal for the selected watchlist and window.

Scope boundaries:

- The output is claim metadata: victim title, group, discovery time, watchlist match, verification label, and source provenance.
- Source access uses the public RansomLook API and safe clear-web RansomLook links.
- Stolen files, credentials, ransom notes, private dumps, forum sessions, onion services, and attacker contact channels remain outside this workflow.
- Alerting, email, webhooks, and messages belong in an authorized downstream system; schedule the Actor and diff stable `claimId` values there.
- A matched organization enters triage as an unverified public claim, with incident confirmation handled through authorized corroboration.

### Builder's note

I built this Actor around RansomLook's two structured public feeds: the posts feed supplies compact group, title, and discovery fields, while the recent feed can enrich a matching claim with a safe detail link. I found that keeping both `discoveredAt` and `detectedAt` in every row makes source time and collection time easy to compare. The normalized `claimId`, matched-value array, source URL, and `verificationStatus` then give an agent or analyst a compact handoff from triage to authorized corroboration.

### Scope and responsible use

Use this Actor only for lawful defensive security research and organizations you are authorized to monitor. Handle watchlist values and any incident context as confidential business information. Follow applicable law, data-protection obligations, source terms, and your incident-response policy. RansomLook is an independent source and this Actor is not affiliated with it.

### Task publication map

`TASK_SEO_PACK.json` reviews the full 50-task ceiling and keeps only materially distinct watchlist workflows. The backlog holds distinct domain, supplier, company-name, brand, and longer-window scenarios; the launch subset activates after exact private canaries produce a useful output preview. Public task creation is a separate approval step.

# Actor input Schema

## `watchlist` (type: `array`):

Names, brands, or domains to compare with public ransomware claim titles, such as `example.com` or `Example Holdings`. Provide 1–100 unique values; URLs are normalized to their hostname. This is a defensive watchlist, not a list of stolen records, credentials, or private forum targets.

## `lookbackDays` (type: `integer`):

Number of recent days requested from the public RansomLook posts feed, from 1 through 30. Defaults to 7, which is suitable for recurring daily monitoring and keeps the source request bounded. This is not a guarantee that a claim was first published inside the window.

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

Hard maximum number of matched claim records persisted in this run. Defaults to 25 and caps at 500; each persisted match is one `matched-claim` event. A lower cap limits output and event charges, but it may leave additional matches in the source window.

## `matchMode` (type: `string`):

Use `strict` for token-boundary name matching and exact domain matching, or `contains` for broader name matching when the source uses shortened company names. Defaults to `strict` to reduce false positives. This changes matching only; it does not prove or score the underlying breach claim.

## `groupAllowlist` (type: `array`):

Optional ransomware group labels that a watchlist match must use, such as `qilin` or `lockbit`. Provide 1–50 distinct labels, or leave this empty to include every group. Matching is case- and punctuation-insensitive against the public RansomLook group label. This filter narrows triage; it does not verify a claim or discover groups absent from the source.

## `excludeClaimIds` (type: `array`):

Optional stable claim IDs from an earlier Dataset that this run should suppress, such as `ransomlook:0123456789abcdef0123`. Provide up to 500 IDs, or leave this empty to return every current match. This enables stateless delta-only monitoring because the caller controls the baseline. It does not delete source records or persist a cross-run watchlist state.

## Actor input object example

```json
{
  "watchlist": [
    "example.com"
  ],
  "lookbackDays": 7,
  "maxResults": 25,
  "matchMode": "strict",
  "groupAllowlist": [],
  "excludeClaimIds": []
}
```

# Actor output Schema

## `matchedClaims` (type: `string`):

One structured record per new public RansomLook claim matched to the supplied watchlist, with match strength and age fields for analyst triage.

## `runSummary` (type: `string`):

Detailed source, matching, truncation, diagnostic, and charge information.

## `compactOutput` (type: `string`):

Stable terminal outcome for agents and automations.

## `lastRunSummary` (type: `string`):

Compatibility alias for the latest detailed terminal record.

# 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 = {
    "watchlist": [
        "example.com"
    ],
    "lookbackDays": 7,
    "maxResults": 25,
    "matchMode": "strict",
    "groupAllowlist": [],
    "excludeClaimIds": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/ransomware-breach-monitor").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 = {
    "watchlist": ["example.com"],
    "lookbackDays": 7,
    "maxResults": 25,
    "matchMode": "strict",
    "groupAllowlist": [],
    "excludeClaimIds": [],
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/ransomware-breach-monitor").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 '{
  "watchlist": [
    "example.com"
  ],
  "lookbackDays": 7,
  "maxResults": 25,
  "matchMode": "strict",
  "groupAllowlist": [],
  "excludeClaimIds": []
}' |
apify call khadinakbar/ransomware-breach-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,khadinakbar/ransomware-breach-monitor"
        }
    }
}

```

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/WJ8l0hf31fN92aqD5/builds/BxFOKGgds2gMBl6kb/openapi.json
