Open a CSV file to check its structure: every record against the header’s field count, blank and duplicate column names, stray quotes, mixed line endings and blank lines. Add optional rules per column, such as integer, date, email, required, unique, allowed values or a regular expression, and each problem is listed with its data row, column and value. Rules use the Frictionless Table Schema vocabulary. The file is checked in your browser, not uploaded.
How to validate a CSV file
- Open a
.csv,.tsvor.txtfile. The delimiter and a UTF-8 or UTF-16 byte-order mark are detected; choose another delimiter or a legacy encoding in the import settings if the columns look wrong. - Optionally enter the number of columns every record must have. Left empty, the header’s column count is used.
- Optionally add rules for the columns you care about: a type, whether a value is required or must be unique, allowed values, a minimum and maximum, a length range or a pattern.
- Run the check and work through the report: errors first, then warnings. Fix values in the CSV editor or tidy them with Clean CSV, then validate again.
To see each column’s types, blanks and distinct values before you write rules, profile the file with Analyze CSV.
Structural checks
| Field count (error) | A record has more or fewer fields than the header, or than the number you entered. RFC 4180 expects every record to have the same number of fields; a mismatch usually means an unquoted delimiter or a missing value. |
|---|---|
| Blank header (error) | A column name is empty or only spaces. The report gives its position. |
| Duplicate header (error) | Two column names are the same after trimming spaces. The report gives both positions. |
| Stray quote (warning) | A quote character appears inside an unquoted value, such as 5" screen. The value is kept as written; the report gives the count for the file. |
| Text after a closing quote (warning) | Characters follow a closing quote before the next delimiter, as in "abc"x. |
| Mixed line endings (warning) | The file mixes CRLF, LF and CR record endings. The report counts each kind. |
| Blank lines (warning) | Empty lines between records. They are skipped, and the report counts them. |
| Surrounding spaces (warning) | A value has spaces before or after its text. On by default; values that are only spaces are not reported. |
A quoted value that never closes stops the check with an error naming the record where it starts, because the rest of the file can’t be split into records reliably.
Column rules
| Type: integer | Optional sign and digits only, such as -12 or 007. Values beyond ±9,007,199,254,740,991 are reported, so use a text rule with a pattern for long IDs. |
|---|---|
| Type: number | Plain decimal notation with a point, such as 3.5, -0.25 or 1e3. No thousands separators, currency or surrounding spaces. |
| Type: boolean | true or false in any letter case. 1, 0, yes and no are reported. |
| Type: date, datetime | A real calendar date written YYYY-MM-DD, so 2024-02-30 is reported. A datetime adds a time (2024-03-05T09:30, optional seconds and a Z or +02:00 offset). |
| Type: string with a format | Email (a simple name@domain.tld shape check, not a deliverability test), URI (an absolute URL with a scheme) or UUID (versions 1–8). |
| Required | The value must not be empty. Without it, empty values pass every other rule. |
| Unique | No value may repeat in the column. The report names the row where it first appeared. Empty values are not compared. |
| Allowed values | The value must equal one of the listed values exactly, including case and spaces. |
| Minimum, maximum | Inclusive bounds for integer and number columns, or ISO dates for date and datetime columns. |
| Minimum and maximum length | Counted in Unicode characters, so é and 日 count as one each. |
| Pattern | A regular expression that must match the whole value, as Table Schema requires; for example [A-Z]{2}\d{4}. Matching is case-sensitive. |
A rule applies to the column whose header matches its name exactly; rules for columns that aren’t in the file are skipped. Rules can be saved as a Table Schema JSON file and loaded again for the next export; unknown types and keys in a loaded schema are ignored.
Reading the report
- Row numbers count data records after the header (the header is row 0). A value with a line break inside quotes is still one record, so a row number can differ from the line number in a text editor.
- Each issue names its column and quotes the value, so you can search for it in the CSV viewer or the editor.
- Errors break the structure or a rule; warnings point to data that is valid CSV but often causes import problems.
- Up to 5,000 issues are listed. Beyond that, the totals per kind of issue are still counted and the list is marked as truncated.
Limits and privacy
The validator reads one record at a time, so files larger than the 25 MB interactive limit are checked in streaming mode in a background worker, with progress and cancellation. In streaming mode, records with fewer fields than the header are currently padded before the check, so only records with extra fields are reported as a field-count error.
Validation runs in your browser. The CSV is not uploaded to a server.
Example
A signup export checked with four rules: id is a required, unique integer; email is a required string in email format; signup_date is a date; plan allows basic, pro and team. The output is the validator’s report, one issue per line after the summary: an impossible date, an email without a domain suffix, Pro in the wrong case, a repeated id, a missing email, and team with a trailing space, which is both a warning and not an allowed value.
id,email,signup_date,plan 1,ana@example.com,2024-02-30,pro 2,kim@example,2024-03-01,Pro 2,bao@example.com,2024-03-04,basic 4,,2024-03-05,team
{"rows":4,"errors":6,"warnings":1,"truncated":false}
{"code":"type","row":1,"column":"signup_date","value":"2024-02-30","params":{"type":"date"}}
{"code":"format","row":2,"column":"email","value":"kim@example","params":{"format":"email"}}
{"code":"enum","row":2,"column":"plan","value":"Pro","params":{"allowed":"basic, pro, team"}}
{"code":"unique","row":3,"column":"id","value":"2","params":{"first":2}}
{"code":"whitespace","row":4,"column":"plan","value":"team ","params":{}}
{"code":"required","row":4,"column":"email","value":"","params":{}}
{"code":"enum","row":4,"column":"plan","value":"team ","params":{"allowed":"basic, pro, team"}}Questions and answers
Why is a value with spaces reported against an allowed-values list?
Rules compare the value exactly as written, without trimming, so team is not team. Trim the column with Clean CSV or fix the export.
Does validation change my file?
No. It only reads the file and reports what it finds. Fix the issues in the editor or the source system.
Can I reuse the same rules for every monthly export?
Yes. Save the rules as a Table Schema JSON file and load it the next time; rules are matched to columns by name.