Random sample CSV rows with a seed
This seeded CSV row sampler selects an exact number of data records without replacement while keeping the original header.
Run — free
Supply CSV text, a sample size, and an integer seed; the same three inputs always produce the same sampled CSV. It is especially useful when a review, test, demonstration, or audit needs a smaller dataset that collaborators can recreate exactly, without relying on a spreadsheet session or an unpredictable random generator.
Create a random subset that colleagues can reproduce
Ordinary random sampling is convenient until someone needs to repeat it. A spreadsheet may choose different records after recalculation, while an undocumented script can leave reviewers wondering whether its output changed between runs. This tool makes the seed part of the input, alongside the CSV text and requested sample size. Identical inputs therefore yield identical selected records, which makes the result suitable for versioned experiments, review notes, and repeatable quality checks. The first CSV record is always treated as the header and is always retained. Sampling applies only to the data records beneath it, and each selected record can appear at most once. The returned records remain in their original relative order, so the smaller file is easier to compare with its source even though selection itself is random. Quoted fields may include commas, escaped quotes, or line breaks; record boundaries are recognized without flattening or rebuilding their contents. The output is ready to save or pass to another CSV-aware step.
Choose the sample size and seed deliberately
Set sample_size to the exact number of data records required. A value of zero is valid and returns the header alone, which can be useful for producing an empty schema-bearing fixture. The size cannot exceed the number of available data records because this is sampling without replacement: asking for more distinct rows than exist would make the requested result impossible. In that case the request returns a clear input error instead of silently duplicating records or reducing the requested size. The seed must be a safe integer. It is not a security secret and does not need to be unpredictable; its purpose is to name one reproducible selection. Teams often derive a simple seed from an experiment number, test case, or review round and record it beside the result. Changing only the seed usually chooses a different subset, while restoring the earlier seed restores the earlier subset. Keep the source CSV unchanged when reproducibility matters, because row additions, removals, or reordering change the population being sampled.
Use sampled CSV responsibly in testing and review
A random subset is helpful for quick inspection, pipeline smoke tests, demonstrations, and distributing manageable fixtures, but it does not automatically become statistically representative. Rare categories can be absent by chance, especially when the requested sample is small. If every category must appear, use a stratified process rather than treating an unrestricted random sample as a guarantee. This capability deliberately performs no network calls, enrichment, type conversion, delimiter conversion, or data cleaning. It preserves the selected raw CSV records and joins them beneath the original header, avoiding formatting surprises such as rewritten dates or normalized numbers. Quoted multiline records are kept intact. Blank physical lines beneath the header are records too, because discarding them would alter the supplied population. For automated workflows, store the seed, sample size, and a stable copy or checksum of the source beside the output. That small audit trail lets another person recreate the exact sample and distinguish a changed algorithm input from a changed downstream analysis. API requests use $0.002; the browser version performs the same deterministic calculation locally.
What you can do with it
Build repeatable test fixtures
Select a compact CSV subset for integration tests and keep the seed with the fixture so failures can be reproduced.
Share a manageable review file
Give a reviewer fewer records while preserving the header, raw record formatting, and a reproducible selection method.
Compare experimental runs
Use the same sampled rows across alternative transformations or models so input differences do not distort the comparison.
FAQ
Can the same row be selected twice?
No. Sampling is performed without replacement, so every selected data record has a distinct source position.
Does the output keep the CSV header?
Yes. The first record is preserved as the header and sampling applies only to subsequent records.
What makes the result deterministic?
The integer seed initializes a fixed pseudorandom selection algorithm. The same CSV, sample size, and seed produce the same output.
What happens when the sample is larger than the CSV?
The request fails with an invalid input error because a larger distinct sample cannot be drawn without replacement.
Are quoted or multiline fields supported?
Yes. Quoted commas, escaped double quotes, and line breaks inside quoted fields are recognized when records are separated.
How much does an API request cost?
Each API request costs $0.002. The browser version runs the same pure calculation locally.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/data/random-sample-rows \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"csv":"id,name,team\n1,Ada,Blue\n2,Grace,Red\n3,Linus,Blue\n4,Margaret,Green\n5,Donald,Red","sample_size":3,"seed":42}'const res = await fetch("https://api.kit.forhosting.com/data/random-sample-rows", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"csv": "id,name,team\n1,Ada,Blue\n2,Grace,Red\n3,Linus,Blue\n4,Margaret,Green\n5,Donald,Red",
"sample_size": 3,
"seed": 42
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/data/random-sample-rows",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"csv": "id,name,team\n1,Ada,Blue\n2,Grace,Red\n3,Linus,Blue\n4,Margaret,Green\n5,Donald,Red",
"sample_size": 3,
"seed": 42
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/data/random-sample-rows", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"csv":"id,name,team\\n1,Ada,Blue\\n2,Grace,Red\\n3,Linus,Blue\\n4,Margaret,Green\\n5,Donald,Red","sample_size":3,"seed":42}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"csv":"id,name,team\n1,Ada,Blue\n2,Grace,Red\n3,Linus,Blue\n4,Margaret,Green\n5,Donald,Red","sample_size":3,"seed":42}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/data/random-sample-rows", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"csv": "id,name,team\n1,Ada,Blue\n2,Grace,Red\n3,Linus,Blue\n4,Margaret,Green\n5,Donald,Red",
"sample_size": 3,
"seed": 42
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "data.random_sample_rows",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |