CSV (Comma-Separated Values) remains the universal format for data exchange. Despite its simplicity, CSV handling has many gotchas—encoding issues, delimiter confusion, and malformed data. This guide covers everything from basic parsing to handling edge cases.
Key Takeaways
- 1Never use simple split(\",\")—quoted fields with commas will break
- 2Fields with commas, quotes, or newlines must be wrapped in double quotes
- 3Escape quotes by doubling them: \"\" represents a single \"
- 4Add UTF-8 BOM (\\uFEFF) for Excel compatibility with non-ASCII characters
- 5Prefix formula-like values (=, +, -, @) to prevent CSV injection attacks
CSV Format Basics
A CSV file stores tabular data as plain text. Each line is a row, and values are separated by commas (or other delimiters).
name,email,age,city
John Doe,john@example.com,28,New York
Jane Smith,jane@example.com,34,Los Angeles
Bob Wilson,bob@example.com,45,Chicago| Component | Description |
|---|---|
| Header row | First row typically contains column names |
| Delimiter | Character separating values (comma, tab, semicolon) |
| Record | One row of data (one line) |
| Field | Individual value within a record |
| Quoting | Fields containing delimiters are wrapped in quotes |
Despite "comma" in the name, CSV files often use semicolons (common in Europe where comma is the decimal separator) or tabs (TSV). Always check or detect the actual delimiter.
2Handling Special Characters
Fields containing commas, quotes, or newlines must be handled carefully using quoting rules.
name,description,price
"Laptop, 15-inch","High-performance laptop",999.99
"Monitor ""Pro""","27-inch 4K display",449.00
"Desk
Chair","Ergonomic office chair
with lumbar support",299.99- 1If a field contains the delimiter (comma), wrap it in double quotes
- 2If a field contains double quotes, escape them by doubling:
- 3 represents one
- 4,
- 5,
Never use simple string.split(",") for CSV parsing—it fails on quoted fields with commas. Use a proper parser or our conversion tool.
Parsing CSV in JavaScript
For simple CSVs without special characters, basic parsing works. For production, use a library or handle edge cases.
// Simple parsing (only for basic CSVs without quotes)
function parseSimpleCSV(csv) {
const lines = csv.trim().split('\n');
const headers = lines[0].split(',');
return lines.slice(1).map(line => {
const values = line.split(',');
return headers.reduce((obj, header, i) => {
obj[header.trim()] = values[i]?.trim() || '';
return obj;
}, {});
});
}
// Usage
const data = parseSimpleCSV(`name,age,city
John,28,NYC
Jane,34,LA`);
// [{name: "John", age: "28", city: "NYC"}, ...]// Robust parsing with quote handling
function parseCSV(csv, delimiter = ',') {
const result = [];
let row = [];
let field = '';
let inQuotes = false;
for (let i = 0; i < csv.length; i++) {
const char = csv[i];
const next = csv[i + 1];
if (inQuotes) {
if (char === '"' && next === '"') {
field += '"';
i++; // Skip escaped quote
} else if (char === '"') {
inQuotes = false;
} else {
field += char;
}
} else {
if (char === '"') {
inQuotes = true;
} else if (char === delimiter) {
row.push(field);
field = '';
} else if (char === '\n' || (char === '\r' && next === '\n')) {
row.push(field);
result.push(row);
row = [];
field = '';
if (char === '\r') i++;
} else if (char !== '\r') {
field += char;
}
}
}
if (field || row.length) {
row.push(field);
result.push(row);
}
return result;
}Convert CSV to JSON Instantly
Paste your CSV and get properly formatted JSON with one click.
Open CSV to JSON Converter4CSV to JSON Conversion
Converting CSV to JSON creates an array of objects, using header values as keys.
// CSV to JSON with type inference
function csvToJson(csv, options = {}) {
const { delimiter = ',', parseNumbers = true } = options;
const rows = parseCSV(csv, delimiter);
if (rows.length < 2) return [];
const headers = rows[0].map(h => h.trim());
return rows.slice(1).map(row => {
const obj = {};
headers.forEach((header, i) => {
let value = row[i]?.trim() || '';
// Type inference
if (parseNumbers && value !== '') {
const num = Number(value);
if (!isNaN(num)) value = num;
}
if (value === 'true') value = true;
if (value === 'false') value = false;
if (value === 'null') value = null;
obj[header] = value;
});
return obj;
});
}
// Result:
// [
// { "name": "John", "age": 28, "active": true },
// { "name": "Jane", "age": 34, "active": false }
// ]| CSV Value | JSON Type | Notes |
|---|---|---|
| 28 | number | Numeric strings become numbers |
| true/false | boolean | Case-sensitive boolean detection |
| null | null | Literal "null" string |
| (empty) | "" | Empty string, not null |
| "quoted,text" | "quoted,text" | Quotes stripped, content preserved |
5JSON to CSV Conversion
Converting JSON arrays to CSV requires extracting headers from object keys and properly escaping values.
function jsonToCsv(data, options = {}) {
const { delimiter = ',', includeHeaders = true } = options;
if (!Array.isArray(data) || data.length === 0) return '';
// Get all unique keys across all objects
const headers = [...new Set(
data.flatMap(obj => Object.keys(obj))
)];
const escapeField = (value) => {
if (value === null || value === undefined) return '';
const str = String(value);
// Quote if contains delimiter, quote, or newline
if (str.includes(delimiter) || str.includes('"') || str.includes('\n')) {
return '"' + str.replace(/"/g, '""') + '"';
}
return str;
};
const rows = data.map(obj =>
headers.map(h => escapeField(obj[h])).join(delimiter)
);
if (includeHeaders) {
rows.unshift(headers.map(escapeField).join(delimiter));
}
return rows.join('\n');
}
// Usage
const csv = jsonToCsv([
{ name: 'John', city: 'New York' },
{ name: 'Jane', city: 'Los Angeles' }
]);
// "name,city\nJohn,New York\nJane,Los Angeles"Flatten nested JSON before CSV conversion. For { user: { name: "John" } }, create a "user.name" column or extract to top level.
Character Encoding Issues
Encoding problems cause garbled text (mojibake). CSV files commonly use UTF-8 or legacy encodings like Windows-1252.
// Reading CSV with specific encoding (Node.js)
const fs = require('fs');
const iconv = require('iconv-lite');
// UTF-8 (default for modern files)
const utf8Content = fs.readFileSync('data.csv', 'utf8');
// Windows-1252 (common for Excel exports)
const buffer = fs.readFileSync('legacy.csv');
const win1252Content = iconv.decode(buffer, 'win1252');
// Browser: Read with encoding detection
async function readCSVFile(file) {
const buffer = await file.arrayBuffer();
// Try UTF-8 first
try {
const decoder = new TextDecoder('utf-8', { fatal: true });
return decoder.decode(buffer);
} catch {
// Fall back to Windows-1252
const decoder = new TextDecoder('windows-1252');
return decoder.decode(buffer);
}
}
// Add BOM for Excel UTF-8 compatibility
const bom = '\uFEFF';
const csvWithBom = bom + csvContent;| Encoding | When Used |
|---|---|
| UTF-8 | Modern standard, supports all characters |
| UTF-8 with BOM | Excel on Windows needs BOM for UTF-8 |
| Windows-1252 | Legacy Windows/Excel files |
| ISO-8859-1 | Western European legacy systems |
| Shift-JIS | Japanese legacy systems |
When creating CSVs for Excel, add a UTF-8 BOM (\\uFEFF) at the start. Without it, Excel may misinterpret non-ASCII characters.
7Excel Compatibility Tips
Excel has specific behaviors that can break CSV imports. Follow these guidelines for seamless compatibility.
- Add UTF-8 BOM for non-ASCII characters (Excel needs it)
- Use semicolon delimiter for European locales where comma is decimal separator
- Prefix formula-like values with single quote: \
- ,
- ,
- ,
- ,
// Excel-safe CSV generation
function toExcelCSV(data, locale = 'en-US') {
// Use semicolon for European locales
const delimiter = ['de', 'fr', 'it', 'es', 'nl', 'pt']
.some(l => locale.startsWith(l)) ? ';' : ',';
const escapeForExcel = (value) => {
let str = String(value ?? '');
// Prevent formula injection
if (/^[=+\-@]/.test(str)) {
str = "'" + str;
}
// Preserve leading zeros (e.g., zip codes)
if (/^0\d+$/.test(str)) {
str = "'" + str;
}
// Quote if needed
if (str.includes(delimiter) || str.includes('"') || str.includes('\n')) {
str = '"' + str.replace(/"/g, '""') + '"';
}
return str;
};
// Generate with BOM
return '\uFEFF' + /* csv content */;
}8CSV Best Practices
Follow these guidelines to create reliable, interoperable CSV files.
- Always include a header row with clear, unique column names
- Use UTF-8 encoding with BOM for maximum compatibility
- Quote all fields containing special characters (delimiter, quotes, newlines)
- Be consistent: same number of fields in every row
- Use ISO 8601 dates (YYYY-MM-DD) for unambiguous parsing
- Avoid trailing delimiters (extra comma at end of lines)
- Document your delimiter, encoding, and date format
- Validate data after parsing—check for expected types and ranges
Good CSV:
id,name,email,created_date,amount
1,John Doe,john@example.com,2024-01-15,1234.56
2,"Jane ""JD"" Smith",jane@example.com,2024-02-20,789.00
3,Bob Wilson,bob@example.com,2024-03-10,
Bad CSV (common issues):
id,name,email,created_date,amount,
1,John Doe,john@example.com,01/15/24,1,234.56
2,Jane "JD" Smith,jane@example.com,,789
3,Bob Wilson,bob@example.com,2024-03-10,0.00,extraWhen in doubt, quote everything. Most parsers handle quoted fields well, and it prevents ambiguity with special characters.
Frequently Asked Questions
What is the difference between CSV and TSV?
CSV uses commas as delimiters; TSV (Tab-Separated Values) uses tabs. TSV avoids quoting issues since tabs rarely appear in data. Both are plain text formats. Most CSV parsers accept a delimiter parameter to handle either format.
Why does Excel show my CSV data in one column?
Excel isn’t recognizing your delimiter. This happens with: 1) Semicolon-delimited files on comma-locale systems (or vice versa), 2) Tab-delimited files imported as CSV, 3) Wrong encoding. Use Excel’s ’Data > From Text/CSV’ with explicit delimiter selection instead of double-clicking the file.
How do I handle CSV files with different delimiters?
Detect the delimiter by analyzing the first few lines: count occurrences of comma, semicolon, and tab, then use the most consistent one. Alternatively, let users specify the delimiter or use libraries like Papa Parse that auto-detect.
Why are numbers showing as scientific notation in Excel?
Excel auto-formats large numbers (and long digit strings like account numbers) as scientific notation. To prevent this: 1) Format the column as Text before pasting, 2) Prefix values with apostrophe in CSV, or 3) Use the ’From Text/CSV’ import with column type specification.
How do I prevent CSV injection attacks?
CSV injection (formula injection) occurs when data starting with =, +, -, @ is interpreted as a formula by spreadsheet software. Prevent it by: 1) Prefixing such values with apostrophe or tab, 2) Wrapping in quotes and adding a space, 3) Stripping or escaping dangerous prefixes on import.