A CSV is the simplest possible way to represent a table of data: each row on its own line, each column separated by a comma. The first line is usually headers. Every spreadsheet and every programming language reads it. Four ways to make one — pick the one that matches where your data already lives.
1. From a spreadsheet (easiest)
Excel, Google Sheets, Apple Numbers, and LibreOffice Calc all export to CSV in two clicks:
- Excel: File → Save As → choose "CSV UTF-8 (Comma delimited) (*.csv)". Plain "CSV (Comma delimited)" uses Windows-1252 and will mangle non-ASCII. Always pick the UTF-8 variant.
- Google Sheets: File → Download → Comma-separated values (.csv).
- Apple Numbers: File → Export To → CSV.
Use this when the data is already in a spreadsheet. No escaping or formatting to get wrong — the app handles all of it.
2. From a text editor (for tiny files)
CSV is plain text, so any editor works. Type your data with commas between fields and newlines between rows, save with a .csv extension:
name,role,hire_date Ada Lovelace,engineer,1843-10-12 Grace Hopper,admiral,1944-07-02 Katherine Johnson,mathematician,1961-04-01
If any field contains a comma, a newline, or a double quote, wrap the whole field in double quotes and double up any internal quotes:
name,quote Ada Lovelace,"She said, ""hi""" Grace Hopper,"known for COBOL, FLOW-MATIC"
Saving in a UTF-8-aware editor (VS Code, Sublime, Notepad on Windows 10+) keeps accented characters intact. Good for small files and for debugging an existing CSV; brittle for anything more than about 20 rows.
3. From code (Python, Node, anywhere)
When the data lives in a program, write it straight to CSV from there:
Python:
import csv
rows = [
{"name": "Ada Lovelace", "role": "engineer"},
{"name": "Grace Hopper", "role": "admiral"},
]
with open("out.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["name", "role"])
writer.writeheader()
writer.writerows(rows)Node.js (no library):
import { writeFileSync } from "node:fs";
const rows = [
{ name: "Ada Lovelace", role: "engineer" },
{ name: "Grace Hopper", role: "admiral" },
];
const headers = Object.keys(rows[0]);
const escape = (v) =>
/[",\n]/.test(v) ? `"${String(v).replace(/"/g, '""')}"` : v;
const csv = [
headers.join(","),
...rows.map((r) => headers.map((h) => escape(r[h])).join(",")),
].join("\n");
writeFileSync("out.csv", csv, "utf-8");Use this when the data comes from a database query, an API response, or a generation script. It scales to any size because you can stream row-by-row without holding everything in memory.
4. From JSON (with a converter)
When the data starts as JSON — API response, config file, log output — the fastest path is a direct converter. Paste the JSON into our JSON to CSV tool, adjust delimiter and flatten-nested settings, download. It handles nested objects (dot notation), arrays, and quoting automatically. For Excel-specific output, use the JSON to Excel version which pre-selects UTF-8 BOM and CRLF line endings.
On the command line, jq handles this too: jq -r '(.[0] | keys_unsorted) as $k | $k, (.[] | [.[$k[]]]) | @csv'.
Three gotchas that bite everyone once
- Missing UTF-8 BOM and Excel mangles accents. If the file will be opened in Excel, the file needs to start with the three bytes EF BB BF. Writing from Python?
open('out.csv', 'w', encoding='utf-8-sig')adds the BOM. From our tool, toggle "Excel BOM" on. - Forgetting to escape commas inside fields. A name like
"Smith, John"written unquoted breaks the column count. Always quote fields that contain the delimiter. - CRLF vs LF on Windows. Excel on Windows expects CRLF. LF-only files sometimes work and sometimes get read as one giant row. When in doubt, use CRLF.
FAQ
What is a CSV file?
A plain-text file where each line is one row of data and each field on that line is separated by a comma (or another delimiter). The first line is usually headers. It's the oldest, simplest, most portable tabular data format — every spreadsheet program, every database, every programming language reads it.
How do I create a CSV in Excel?
Type or paste your data into cells, then File → Save As → CSV UTF-8. That's it. Excel handles the delimiters, quoting, and escaping automatically. Open the saved file in a text editor if you want to verify — it should look like rows of comma-separated values with the headers on line 1.
How do I create a CSV in Google Sheets?
Type or paste your data, then File → Download → Comma-separated values (.csv). Same result as Excel. Note Google Sheets exports UTF-8 by default, which is usually what you want.
Can I create a CSV in Notepad or a plain text editor?
Yes — that's all a CSV file is. Type your data with commas between fields and newlines between rows, save with a .csv extension, done. Useful for tiny files (under 20 rows) and for testing. For anything larger, a spreadsheet or code is less error-prone because you don't have to hand-quote fields that contain commas or newlines.
How do I make a CSV from JSON?
Use a converter. Our free JSON to CSV tool takes an array of objects and produces a CSV in the right shape, with nested objects flattened into dot-notation columns. For command-line conversion, `jq` can do it: `jq -r '(.[0] | keys_unsorted) as $k | $k, (.[] | [.[$k[]]]) | @csv' input.json`. Python: `import csv, json; ...`. Node: several npm packages handle it in ~10 lines.
How do I write a CSV from Python code?
Python has a built-in csv module: `import csv; with open('out.csv', 'w', newline='', encoding='utf-8') as f: writer = csv.DictWriter(f, fieldnames=['name', 'role']); writer.writeheader(); writer.writerows(rows)`. The `newline=''` part matters — it stops Python from adding extra line breaks on Windows.
How do I write a CSV from Node.js or JavaScript?
Without a library, it's about 15 lines: map each object through an escape-and-join function, add a header row, join with newlines. With a library, `fast-csv`, `csv-stringify`, or `papaparse` all do the job in 3-5 lines. Papa Parse also runs in the browser, which is handy for client-side exports.
What encoding should I use?
UTF-8 with a BOM if the file will be opened in Excel; UTF-8 without a BOM for everything else. The BOM is three bytes (EF BB BF) at the start of the file that tells Excel to use UTF-8 instead of Windows-1252. Without it, Excel mangles accented characters, emoji, and CJK text. Our JSON to Excel tool has this toggled on by default.
Comma vs. semicolon — which delimiter?
Comma is the default and what most tools expect. Semicolon is common in European locales because the comma is the decimal separator there — if you're sharing data with someone in Germany or France, semicolon-delimited avoids numeric collisions. Tab-separated (TSV) is the other common variant, popular in scientific data and easy to paste into spreadsheets.
How do I handle special characters in CSV fields?
Wrap the field in double quotes. If the field contains a double quote, escape it by doubling: a cell containing `She said "hi"` is written in CSV as `"She said ""hi"""`. Fields containing commas, newlines, or quotes must be quoted. Fields without any of those don't need to be, though 'quote everything' is a defensible style too.
Should I include a header row?
Usually yes. Every CSV reader either expects one (treating row 1 as field names) or lets you configure it. Without headers, consumers have to guess what each column means. The only real case for skipping headers is when the CSV is an internal pipe between two systems you control and you want to save a row of bytes.
Related
- · JSON to CSV converter — the fastest way if your data is already JSON.
- · JSON to Excel — Excel-compatible defaults (UTF-8 BOM, CRLF, quoted).
- · CSV to JSON — the reverse direction.