# NL Test Data Generator: BSN, IBAN, Credit Card (`codeclouds/nl-testdata-generator`) Actor

Generate checksum-valid, safe-to-use test identifiers for QA: RvIG-reserved test BSNs, mod-97 NL IBANs, official Visa/Mastercard/Amex sandbox card numbers, Dutch phone numbers, and bonus KvK/BTW formats.

- **URL**: https://apify.com/codeclouds/nl-testdata-generator.md
- **Developed by:** [Dennis](https://apify.com/codeclouds) (community)
- **Categories:** Developer tools, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 generated-identifiers

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

## NL Test Data Generator — BSN, IBAN & Credit Card Test Numbers 🇳🇱

Generate checksum-valid, **safe-to-use** test identifiers for software QA: Dutch BSN numbers from the officially reserved RvIG test range, mod-97-valid NL IBANs, Luhn-valid Visa/Mastercard/American Express sandbox card numbers, Dutch phone numbers, and bonus KvK/BTW number formats. Every value is generated on the fly by a pure, deterministic algorithm — no scraping, no external calls, no database of real people or accounts.

**⚠️ For test/development purposes only.** These identifiers must never be used as a substitute for a real BSN/IBAN/credit card in production, and never for identity fraud or to misrepresent a real transaction. See the Legal section below.

### When should an AI agent use this?

- "Give me 10 valid test BSN numbers I can use in my Dutch registration form's unit tests."
- "Generate a Visa and a Mastercard test card number I can use to test my checkout flow's Luhn validation."
- "I need a reproducible set of fake but checksum-valid Dutch IBANs for a fixture file — use seed 42 so it's the same every time."
- "Build me a realistic-looking Dutch test identity: BSN, IBAN, phone number, KvK and BTW number, all in one record."
- "Does this credit card number pass the Luhn check? Give me a known-good and a known-bad example."
- "I need 500 fake BSNs for a load test — but they must never accidentally collide with a real citizen's number."

### What this Actor does

- **BSN (Dutch citizen service number)**: samples from the exact, officially published RvIG test-BSN list (the "99999" range from RvIG's own omnummertabel) — every value is guaranteed to never be issued to a real person. See the Legal section for exactly how this is verified.
- **IBAN (NL)**: generates a mod-97-valid Dutch IBAN using bank code `TEST` (not a registered Dutch bank BIC prefix).
- **Phone number (NL)**: generates numbers using either a real area code with a subscriber number starting in "0" (structurally unassignable under Dutch numbering law) or the 06-9 mobile block (currently reserved but unissued per ACM's numbering report).
- **Credit card**: returns the official, publicly documented sandbox test numbers for Visa, Mastercard and American Express (the same numbers used by major payment processors like Stripe) — Luhn-valid, never linked to a real account.
- **KvK number** (bonus): 8-digit format. Note: the real KvK number format has **no checksum**, so this cannot guarantee non-existence — see disclaimer below.
- **BTW/VAT number** (bonus): `NL` + 9-digit elfproef-valid RSIN + `B` + 2-digit establishment number.
- Optional `seed` parameter for **fully reproducible** runs — same seed, same output, every time.
- 100% deterministic, pure computation — no network calls at runtime, so it's fast, cheap, and never breaks due to an external source changing.

### Why this matters

Using a randomly-typed or hand-picked "fake" BSN/IBAN/credit card number in a test suite carries a real, if small, risk: it might coincidentally be a real, currently-assigned identifier. Existing "fake data" generators on the market produce realistic-looking names/addresses/emails, but very few generate **checksum-correct** national identifiers, and none document exactly which officially reserved test range they draw from. This Actor closes that gap by generating strictly within ranges that are either (a) officially reserved by the issuing authority for testing (RvIG for BSN, card networks for credit cards) or (b) clearly and transparently disclaimed where no such official range exists (IBAN, phone number, KvK, BTW).

### Input

| Field | Type | Description |
|---|---|---|
| `types` | array | Which identifier types to generate: `bsn`, `iban`, `phoneNumber`, `creditCard`, `kvkNumber`, `btwNumber`. Default: all six. |
| `count` | integer | How many identifiers to generate **per selected type**. Default `10`, max `10000`. Note: the BSN pool is a finite official list (906 numbers) — a larger request is automatically capped, see Legal/FAQ. |
| `ibanCountryCode` | string | Currently only `NL` is supported. |
| `creditCardNetwork` | array | Which card networks to draw from: `visa`, `mastercard`, `amex`. Default: all three. |
| `seed` | integer | Optional. Set a fixed number to make repeated runs produce the exact same identifiers — useful for reproducible test fixtures. Omit for a different result every run. |

### Output

One flat JSON record per generated identifier:

```json
{
  "type": "bsn",
  "value": "999999163",
  "isValidChecksum": true,
  "sourceRangeNote": "RvIG-testreeks 99999xxxx (Test-BSN 910-1816 uit de officiële omnummertabel, rvig.nl/testbestanden-bvbsn) — gegarandeerd niet aan een bestaand persoon toegekend."
}
```

```json
{
  "type": "creditCard",
  "value": "4242424242424242",
  "isValidChecksum": true,
  "sourceRangeNote": "Visa-sandboxnummer (publiek gedocumenteerd door Stripe, docs.stripe.com/testing, \"basic card number\")."
}
```

| Field | Description |
|---|---|
| `type` | One of the requested identifier types |
| `value` | The generated identifier itself |
| `isValidChecksum` | Always `true` for this Actor's output — confirms the value passes the relevant checksum (elfproef / mod-97 / Luhn), except for `kvkNumber` where the real-world format has no checksum at all (see disclaimer in `sourceRangeNote`) |
| `sourceRangeNote` | Transparency field: exactly which officially reserved range or publicly documented source this value comes from, and any relevant disclaimer |

### Use cases

- Populate a Dutch citizen-registration form's automated test suite with valid-but-safe BSN numbers
- Test a payment integration's card-brand detection and Luhn validation without touching real card data
- Generate reproducible fixture data for CI pipelines (`seed` parameter)
- Stress-test bulk-import/validation pipelines with thousands of syntactically valid IBANs
- Give an AI coding agent a reliable "tool" for producing valid Dutch test data instead of letting it invent (possibly incorrect) elfproef logic itself

### Pricing

Pay-per-event: **$0.0006 per generated identifier** (`generated-identifier` event), plus Apify's standard actor-start fee. Generating 100 identifiers across two types (e.g. 50 BSN + 50 IBAN) costs roughly $0.06 in generation events.

### Legal & safety

- **BSN**: generated exclusively from the literal, verified list published by RvIG (the Dutch civil registry authority) in its official test-number spreadsheet (`Testdataset testnummers inclusief omnummertabel GBA-V.ods`, via rvig.nl/testbestanden-bvbsn). This Actor downloaded and parsed that exact file rather than trusting a summary of it — the file itself confirmed a `99999xxxx` prefix (906 usable values after excluding one number RvIG itself marked as intentionally invalid). Every generated BSN is one of these exact, officially reserved values — never an independently computed "elfproef-valid-looking" number.
- **IBAN**: bank code `TEST` is not a registered Dutch bank BIC. A valid mod-97 checksum does **not** prove the account exists — never attempt to use a generated IBAN for a real payment.
- **Phone number**: no official Dutch fiction/test number convention (comparable to the North American 555-01xx range) could be confirmed to exist. This Actor uses two independently-sourced, conservative choices instead — see PROJECTINFORMATIE.txt for the full reasoning — but this is a **lower-confidence guarantee** than the BSN range. Do not rely on this for anything beyond format/field validation testing.
- **Credit card**: only the literal, publicly documented official sandbox numbers from Visa/Mastercard/American Express (as published by major certified payment processors) are used — never a self-constructed Luhn-valid number.
- **KvK number**: the real-world format has no checksum digit, so **no generator can guarantee** a random 8-digit number isn't a real, currently registered KvK number. Use only for format/field-validation tests, not as a "guaranteed fake" claim.
- **BTW/VAT number**: no officially published "reserved test RSIN range" exists (unlike BSN) — the same caveat as KvK applies to the 9-digit RSIN portion.
- This Actor is intended **exclusively for software testing and development purposes**. Never use generated identifiers as a substitute for a real BSN, IBAN, or credit card in a production system, in a real financial transaction, or for identity fraud.

### FAQ

**Can I generate more than 906 BSNs in one run?**
No — the officially reserved RvIG test range contains exactly 906 usable numbers (see Legal section). Requesting more than that per run returns only the available 906 and logs a warning; it never recycles duplicates or fabricates numbers outside the official range.

**Why does the BSN range differ slightly from what other sources describe?**
Several summaries describe the range loosely as "starting with 9999". This Actor downloaded RvIG's actual source spreadsheet and confirmed the real prefix is `99999` (five nines) applied to a specific, finite list of numbers — not every number matching that pattern is on RvIG's list. See PROJECTINFORMATIE.txt for the full verification trail.

**Is the phone number as safe as the BSN?**
No — be aware that no Dutch authority publishes an official "test/fiction" phone number range. This Actor's phone numbers rest on a conservative reading of Dutch numbering law and current ACM numbering-status reports, not a dedicated reservation like RvIG's BSN list.

**Can I get the same identifiers again later?**
Yes — set the `seed` input field to any fixed number. The same seed always produces the same sequence of identifiers.

**Does a duplicate credit card number across records mean something is broken?**
No — there are only 5 official sandbox numbers in total (across all 3 networks combined), so duplicates are expected once you request more results than that.

### Keywords

BSN generator, fake BSN, test BSN Nederland, IBAN generator, testrekeningnummer, elfproef, mod 97 controlegetal, Luhn algorithm, credit card test numbers, Visa test card, Mastercard test card, Amex test card, KvK nummer generator, BTW nummer generator, dummy data generator, QA test data, fixture data generator, MCP tool test data

### Related Actors

- [nis2-sbi-sector-mapper](https://apify.com/codeclouds/nis2-sbi-sector-mapper) — another pure rule-engine actor from the same portfolio (no scraping, no external calls at runtime)

### Changelog

- **v0.1** (2026-08-25) — Initial release: BSN (RvIG test range), IBAN (NL, mod-97), phone number (NL), credit card (Visa/Mastercard/Amex sandbox numbers), KvK number, BTW number. Optional `seed` for reproducible runs.

# Actor input Schema

## `types` (type: `array`):

Which types of test identifiers to generate. Each selected type gets its own batch of `count` records.

## `count` (type: `integer`):

How many identifiers to generate per selected type. Note: the BSN pool is a finite, officially published list (906 numbers) — a request larger than that is automatically capped, see README.

## `ibanCountryCode` (type: `string`):

Country scope for generated IBANs. Currently only the Netherlands (NL) is supported.

## `creditCardNetwork` (type: `array`):

Which card networks to draw official sandbox test numbers from.

## `seed` (type: `integer`):

Set a fixed number to make repeated runs produce the exact same identifiers (useful for reproducible test fixtures). Leave empty for a different result on every run.

## Actor input object example

```json
{
  "types": [
    "bsn",
    "iban",
    "phoneNumber",
    "creditCard",
    "kvkNumber",
    "btwNumber"
  ],
  "count": 10,
  "ibanCountryCode": "NL",
  "creditCardNetwork": [
    "visa",
    "mastercard",
    "amex"
  ]
}
```

# Actor output Schema

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

Results stored in the default dataset.

# 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 = {
    "types": [
        "bsn",
        "iban",
        "phoneNumber",
        "creditCard",
        "kvkNumber",
        "btwNumber"
    ],
    "creditCardNetwork": [
        "visa",
        "mastercard",
        "amex"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("codeclouds/nl-testdata-generator").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 = {
    "types": [
        "bsn",
        "iban",
        "phoneNumber",
        "creditCard",
        "kvkNumber",
        "btwNumber",
    ],
    "creditCardNetwork": [
        "visa",
        "mastercard",
        "amex",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("codeclouds/nl-testdata-generator").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 '{
  "types": [
    "bsn",
    "iban",
    "phoneNumber",
    "creditCard",
    "kvkNumber",
    "btwNumber"
  ],
  "creditCardNetwork": [
    "visa",
    "mastercard",
    "amex"
  ]
}' |
apify call codeclouds/nl-testdata-generator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,codeclouds/nl-testdata-generator"
        }
    }
}

```

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/9DRu6ySIsGk7ITwZA/builds/LjIyHsU1LMK846Ms2/openapi.json
