# Apify Dataset JSON Schema Validator (`automation-lab/apify-dataset-json-schema-validator`) Actor

Validate inline JSON records or Apify dataset items against JSON Schema with structured errors and summary counts.

- **URL**: https://apify.com/automation-lab/apify-dataset-json-schema-validator.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.44 / 1,000 record validateds

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?

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

## Apify Dataset JSON Schema Validator

Validate inline JSON records or Apify dataset items against a caller-provided JSON Schema.
This JSON Schema validator writes one typed result per record, preserves the original record,
and reports bounded, structured errors with instance paths and schema paths.
It also stores aggregate valid and invalid counts for recurring data-quality gates.

Use it between extraction and downstream automation when malformed records should be visible
before they reach a database, CRM, spreadsheet, model, or webhook.

### What this Actor does

The Actor compiles your schema once and evaluates every selected record against it.
It supports JSON Schema Draft 7 and Draft 2020-12, including common formats such as email,
URI, date, and date-time.

For every record it exports:

- a `valid` boolean;
- the zero-based source index;
- the complete original record;
- the total validation error count;
- a bounded error list;
- JSON Pointer `instancePath` and `schemaPath` values;
- the failed keyword, message, parameters, and offending value;
- an ISO validation timestamp.

The `SUMMARY` key in the default key-value store contains processed, valid, and invalid counts.

### Who is it for

**Data engineers** can put a deterministic contract check between scraping and loading.

**Actor developers** can test whether dataset output still conforms after a selector or API change.

**Automation operators** can inspect summary counts before triggering a downstream Task.

**QA teams** can export exact failure paths instead of manually comparing large JSON objects.

**CRM and catalog teams** can quarantine invalid records before importing them.

### Why use an Actor for schema validation

A local validator is useful for one file. An Actor is useful when validation belongs in an Apify
workflow: it can read an existing dataset, run on a schedule, expose API and MCP interfaces,
and leave machine-readable output that another Actor, webhook, or integration can consume.

The implementation is deliberately lightweight:

- no browser is started;
- no proxy is used;
- no third-party validation API receives your records;
- the run is bounded by `maxItems`;
- error output is bounded by `maxErrorsPerRecord`.

### Input sources

Choose exactly one source.

#### Inline records

Set `records` to an array of JSON objects. This is best for webhook payloads, API responses,
small files, examples, and CI checks.

#### Apify dataset

Set `datasetId` to an Apify dataset ID or name readable by the run token.
This is best for checking the output of a scraper or an earlier workflow step.
Private datasets require a token with access. An unknown or inaccessible dataset fails the run.

Do not provide `records` and `datasetId` together.

### Input parameters

| Field | Type | Required | Default | Description |
|---|---|---:|---:|---|
| `schema` | object | yes | — | Draft 7 or Draft 2020-12 JSON Schema compiled once for all records. |
| `records` | array | conditional | — | Inline JSON objects. Use exactly one source. |
| `datasetId` | string | conditional | — | Readable Apify dataset ID or name. Use exactly one source. |
| `maxItems` | integer | no | `10` | Maximum records processed, from 1 to 10,000. |
| `maxErrorsPerRecord` | integer | no | `20` | Errors retained per record, from 1 to 100. |

The schema is not generated or modified. Invalid and unsupported schemas fail closed before
records are charged or written.

### Getting started

1. Open the Actor input page.
2. Keep the prefilled product-like schema or paste your own schema.
3. Keep the inline example records, or remove them and enter a dataset ID.
4. Set a bounded `maxItems` for the first run.
5. Run the Actor.
6. Open **Validation results** to inspect one row per record.
7. Open **Validation summary** to read aggregate counts.
8. Use `valid`, `errorCount`, and `SUMMARY.invalidCount` in downstream decisions.

### Inline input example

```json
{
  "schema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "required": ["id", "email"],
    "properties": {
      "id": { "type": "integer" },
      "email": { "type": "string", "format": "email" }
    },
    "additionalProperties": false
  },
  "records": [
    { "id": 1, "email": "support@apify.com" },
    { "id": "2", "email": "not-an-email" },
    { "id": 3 }
  ],
  "maxItems": 100,
  "maxErrorsPerRecord": 20
}
```

This produces one valid row and two invalid rows.

### Validate an Apify dataset

Remove `records` and pass the dataset identifier:

```json
{
  "schema": {
    "type": "object",
    "required": ["url", "title"],
    "properties": {
      "url": { "type": "string", "format": "uri" },
      "title": { "type": "string", "minLength": 1 }
    }
  },
  "datasetId": "YOUR_DATASET_ID",
  "maxItems": 5000,
  "maxErrorsPerRecord": 25
}
```

The Actor reads dataset items in bounded pages and preserves their source order.
When `maxItems` stops the read before source exhaustion, `SUMMARY.sourceTruncated` is `true`.

### Validation result fields

| Field | Meaning |
|---|---|
| `recordIndex` | Zero-based position in the selected source. |
| `sourceType` | `inline` or `dataset`. |
| `sourceDatasetId` | Dataset ID/name, or `null` for inline records. |
| `valid` | Whether the complete record conforms. |
| `errorCount` | Full number of errors found for the record. |
| `errorsTruncated` | Whether only the first configured errors were retained. |
| `errors` | Structured AJV errors with paths, keywords, messages, parameters, and values. |
| `record` | Original validated JSON object. |
| `validatedAt` | ISO 8601 validation timestamp. |

Fields are nullable in the Actor's display schema so integrations remain resilient,
but current successful result rows populate every field except `sourceDatasetId` for inline input.

### Output example

```json
{
  "recordIndex": 1,
  "sourceType": "inline",
  "sourceDatasetId": null,
  "valid": false,
  "errorCount": 2,
  "errorsTruncated": false,
  "errors": [
    {
      "instancePath": "/id",
      "schemaPath": "#/properties/id/type",
      "keyword": "type",
      "message": "must be integer",
      "params": { "type": "integer" },
      "value": "2"
    },
    {
      "instancePath": "/email",
      "schemaPath": "#/properties/email/format",
      "keyword": "format",
      "message": "must match format email",
      "params": { "format": "email" },
      "value": "not-an-email"
    }
  ],
  "record": { "id": "2", "email": "not-an-email" },
  "validatedAt": "2026-01-15T12:00:00.000Z"
}
```

### Summary output

The `SUMMARY` record contains:

```json
{
  "sourceType": "inline",
  "sourceDatasetId": null,
  "totalProcessed": 3,
  "validCount": 1,
  "invalidCount": 2,
  "maxItems": 100,
  "sourceTruncated": false,
  "maxErrorsPerRecord": 20,
  "completedAt": "2026-01-15T12:00:00.000Z"
}
```

A downstream automation can continue only when `invalidCount` equals zero.

### How much does it cost to validate JSON records?

The Actor uses pay-per-event pricing:

- a one-time **Run started** event costs **$0.0003** per run;
- each processed record uses one **Record validated** event;
- on the BRONZE tier, a record currently costs **$0.000728**.

At the BRONZE rate, 10 records cost about **$0.00758**, 100 cost about **$0.0731**,
and 1,000 cost about **$0.7283**, including one start event.
Valid and invalid records have the same processing value and the same item charge.
Schema compilation failures and records never reached because input is invalid are not item-charged.
Always check the live pricing tab for the tier applicable to your account.

### Recurring data-quality workflow

A practical scheduled gate can be built as follows:

1. Run an extraction Actor into an Apify dataset.
2. Pass that dataset ID and the expected schema to this Actor.
3. Read `SUMMARY.invalidCount` through the API.
4. Continue to enrichment or import only when it is zero.
5. Otherwise export invalid rows and route their `errors` array to repair or investigation.
6. Keep prior run summaries to spot changes in failure rate.

This Actor reports current conformance. It does not compare runs or send alerts by itself.

### Error paths and repair hints

`instancePath` points into the record, for example `/contact/email`.
`schemaPath` points into the rule, for example `#/properties/contact/properties/email/format`.
`keyword` identifies the violated constraint, such as `required`, `type`, `format`, or `enum`.
`params` retains machine-readable context such as the missing property or expected type.
`value` shows the value resolved at `instancePath` when available.

For object-level errors such as `required` and `additionalProperties`, the offending value may be
the containing object. Use `params.missingProperty` or `params.additionalProperty` for the exact key.

### API with cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~apify-dataset-json-schema-validator/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "schema":{"type":"object","required":["id"],"properties":{"id":{"type":"integer"}}},
    "records":[{"id":1},{"id":"wrong"}],
    "maxItems":100
  }'
```

Keep tokens in environment variables or secret storage, not committed source code.

### API with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/apify-dataset-json-schema-validator').call({
  schema: {
    type: 'object',
    required: ['id'],
    properties: { id: { type: 'integer' } },
  },
  records: [{ id: 1 }, { id: 'wrong' }],
  maxItems: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### API with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/apify-dataset-json-schema-validator').call(run_input={
    'schema': {
        'type': 'object',
        'required': ['id'],
        'properties': {'id': {'type': 'integer'}},
    },
    'records': [{'id': 1}, {'id': 'wrong'}],
    'maxItems': 100,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use with MCP

Add this Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/apify-dataset-json-schema-validator"
```

#### Claude Desktop, Cursor, and VS Code setup

Use this HTTP MCP configuration in Claude Desktop, Cursor, or VS Code:

```json
{
  "mcpServers": {
    "apify-json-schema-validator": {
      "url": "https://mcp.apify.com?tools=automation-lab/apify-dataset-json-schema-validator"
    }
  }
}
```

Example prompts:

- “Validate these webhook records against this Draft 2020-12 schema and list every invalid path.”
- “Run the Apify dataset JSON Schema validator on dataset ID X, stopping after 500 items.”
- “Read the validation summary and tell me whether the downstream import should continue.”

### Limits and failure behavior

- A run processes at most 10,000 records.
- Each record retains at most 100 errors; `errorCount` still reports the full count.
- Inline records and dataset items must be JSON objects, not primitive values or arrays.
- Draft 7 and Draft 2020-12 are supported; Draft 4 and custom meta-schemas are not promised.
- Remote `$ref` fetching is not enabled. Put required definitions in the supplied schema.
- Dataset access follows the permissions of the Actor run token.
- Extremely complex schemas can require more time than simple type and required-field checks.
- The Actor does not mutate, repair, quarantine, or delete source records.
- The Actor does not monitor prior runs or send notifications.

Malformed input, invalid schemas, conflicting sources, and inaccessible datasets fail the run
with a specific log message. A naturally empty input succeeds with zero summary counts.

### Tips for reliable gates

Start with a small `maxItems` while developing the schema.
Set `additionalProperties: false` only when unexpected fields should block the pipeline.
Use `errorCount` for metrics and `errors` for bounded diagnostics.
Raise `maxErrorsPerRecord` only when downstream users need all failures.
Pin a schema version in your own configuration so contract changes are reviewed.
Keep reusable definitions under `$defs` or `definitions` in the same schema document.

### Legality and responsible use

Only validate records you are authorized to process.
Dataset access does not bypass Apify permissions.
The Actor copies original records into its output dataset, so avoid sending unnecessary secrets,
credentials, health data, or other sensitive fields. Apply suitable dataset retention and access
controls. The Actor does not send records to a third-party validation service.

### Troubleshooting

**Why did the run reject my input immediately?**
Check that `schema` exists and that exactly one of `records` and `datasetId` is present.

**Why can the Actor not open my dataset?**
Confirm the ID or name and ensure the run token can read it.

**Why is `errorCount` larger than `errors.length`?**
The error list reached `maxErrorsPerRecord`; inspect `errorsTruncated` or raise the bound.

**Why is a required-field error's `instancePath` empty?**
The failed rule applies to the containing object. Read `params.missingProperty` for the key.

**Why did a schema fail to compile?**
Check the declared draft, keyword shapes, regular expressions, and local `$ref` definitions.

### Related Automation Lab Actors

- [Dataset Dedup](https://apify.com/automation-lab/dataset-dedup) removes duplicate records before or after validation.
- [Schema-Guided Web Data to Excel](https://apify.com/automation-lab/schema-guided-web-data-to-excel) extracts schema-guided fields and exports them to XLSX.
- [Webpage Structured Data Monitor](https://apify.com/automation-lab/webpage-structured-data-monitor) monitors structured data on public pages.

Use this Actor as a standalone validator when you already have JSON records and need explicit,
portable JSON Schema conformance evidence.

### FAQ

**Does it generate a JSON Schema?**
No. Supply the exact contract you want enforced; schema inference is a different workflow.

**Does it charge invalid records?**
Yes. An invalid record was fully evaluated and produces actionable output.

**Can I validate multiple datasets in one run?**
No. Run one dataset per execution so source identity and summary counts remain unambiguous.

**Can I validate nested objects and arrays?**
Yes. AJV applies your nested schema and reports JSON Pointer paths to failures.

**Can another Actor consume the output?**
Yes. Read the default dataset for row-level results and `SUMMARY` for aggregate counts.

**Can I schedule it?**
Yes. Use an Apify Schedule or invoke it from an Actor/Task chain with a current dataset ID.

# Actor input Schema

## `schema` (type: `object`):

JSON Schema Draft 7 or Draft 2020-12 used to validate every record.

## `records` (type: `array`):

JSON objects to validate. Use this or Dataset ID, not both.

## `datasetId` (type: `string`):

ID or name of an Apify dataset readable with the run token. Use this or Inline records, not both.

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

Stop after validating this many records.

## `maxErrorsPerRecord` (type: `integer`):

Maximum structured validation errors retained for one record. The full count is still reported.

## Actor input object example

```json
{
  "schema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "required": [
      "id",
      "email"
    ],
    "properties": {
      "id": {
        "type": "integer"
      },
      "email": {
        "type": "string",
        "format": "email"
      }
    },
    "additionalProperties": false
  },
  "records": [
    {
      "id": 1,
      "email": "analyst@example.org"
    },
    {
      "id": "2",
      "email": "not-an-email"
    },
    {
      "id": 3
    }
  ],
  "maxItems": 10,
  "maxErrorsPerRecord": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing one validity result for each processed record.

## `summary` (type: `string`):

Aggregate valid and invalid counts for this run.

# 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 = {
    "schema": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "required": [
            "id",
            "email"
        ],
        "properties": {
            "id": {
                "type": "integer"
            },
            "email": {
                "type": "string",
                "format": "email"
            }
        },
        "additionalProperties": false
    },
    "records": [
        {
            "id": 1,
            "email": "analyst@example.org"
        },
        {
            "id": "2",
            "email": "not-an-email"
        },
        {
            "id": 3
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/apify-dataset-json-schema-validator").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 = {
    "schema": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "required": [
            "id",
            "email",
        ],
        "properties": {
            "id": { "type": "integer" },
            "email": {
                "type": "string",
                "format": "email",
            },
        },
        "additionalProperties": False,
    },
    "records": [
        {
            "id": 1,
            "email": "analyst@example.org",
        },
        {
            "id": "2",
            "email": "not-an-email",
        },
        { "id": 3 },
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/apify-dataset-json-schema-validator").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 '{
  "schema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "required": [
      "id",
      "email"
    ],
    "properties": {
      "id": {
        "type": "integer"
      },
      "email": {
        "type": "string",
        "format": "email"
      }
    },
    "additionalProperties": false
  },
  "records": [
    {
      "id": 1,
      "email": "analyst@example.org"
    },
    {
      "id": "2",
      "email": "not-an-email"
    },
    {
      "id": 3
    }
  ]
}' |
apify call automation-lab/apify-dataset-json-schema-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/apify-dataset-json-schema-validator"
        }
    }
}
```

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/zcUobGuNaJoHGnZni/builds/nxfuXUDlK8LvIdf7I/openapi.json
