Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

CSVtoTable

CSVtoTable converts CSV, TSV, and Excel files into interactive HTML tables.

  • Single native binary with embedded frontend assets
  • Standalone HTML output that works offline — data, styles, and scripts all inlined
  • CSV, TSV, and Excel (.xlsx) input, gzip archives included
  • Local files, URLs, standard input, or several files combined into one table
  • BOM and UTF-16 detected automatically; --encoding, --delimiter, --quotechar for the rest
  • Search, per-column filters with clearable chips, sorting, pagination, and virtual scrolling
  • Copy, CSV, JSON, and print exports, plus column show/hide
  • Markdown or raw HTML page title and description, inline or read from a file
  • Five colour themes, switchable in the page or fixed with --theme
  • Themes are just CSS variables — define your own with --css and it joins the picker
  • --css and --js inline your own stylesheet and script, with the live table API exposed
  • Mobile-responsive layout

CSVtoTable demo

Try the live demo — a page built by CSVtoTable from the sample data, served as one static file.

Usage

# Write a standalone page
csvtotable input.csv page.html

# Combine files with the same columns
csvtotable input1.csv input2.csv page.html

# Gzip-compressed CSV files
csvtotable data.csv.gz data.html

# Read an Excel workbook
csvtotable sales.xlsx sales.html

# Fetch CSV directly from a URL
csvtotable https://raw.githubusercontent.com/vividvilla/csvtotable/master/demo/meteorite-landings-1.csv meteorites.html

# Open a temporary page in the default browser
csvtotable data.csv --serve

# Add a title and generate headers for headerless data
csvtotable data.csv data.html --title "Sales" --no-header

# Title and description accept Markdown
csvtotable data.csv data.html --title "Sales for **Q3**" --description "Pulled from \`warehouse\`. See the [runbook](https://example.com)."

# or pass a markdown file as decription
csvtotable data.csv data.html --title "Sales for **Q3**" --description @sales.md

# or use raw HTML instead of Markdown
csvtotable data.csv data.html --title-html '<span>Sales <b>Q3</b></span>'
csvtotable data.csv data.html --title-html '<span>Sales <b>Q3</b></span>' --description-html @description.html

# Paginate instead of showing every row
csvtotable data.csv data.html --page-size 50

# Open in a particular theme
csvtotable data.csv data.html --theme solarized

# Add your own CSS and JavaScript
csvtotable data.csv data.html --css brand.css --js setup.js

# Read stdin and write stdout
curl -L https://example.com/data.csv | csvtotable - - > data.html

# Explore all the available options
csvtotable --help

Install

uvx, pipx, or pip

Run without installing:

uvx csvtotable data.csv data.html

Or install it:

pipx install csvtotable
uv tool install csvtotable
pip install csvtotable  # inside a virtual environment

npx or npm

npx @vividvilla/csvtotable data.csv data.html   # run without installing
npm install --global @vividvilla/csvtotable     # or install globally

To run a particular published version:

uvx csvtotable@X.Y.Z data.csv data.html
npx @vividvilla/csvtotable@X.Y.Z data.csv data.html

Homebrew

brew install vividvilla/tap/csvtotable

Standalone binary

Download an archive from GitHub Releases, verify it with SHA256SUMS, and place csvtotable (csvtotable.exe on Windows) on your PATH.

Prebuilt binaries support Linux x86-64/ARM64, macOS 12+ x86-64/Apple Silicon, and Windows 10+ x86-64.

Styling

The page is plain semantic HTML, and every element CSVtoTable owns carries a csvtotable- class. These are the stable hooks:

Hook Element
.csvtotable <main>, the page root
.csvtotable-header <header> wrapping the title and description
.csvtotable-title <h1> page heading
.csvtotable-description description block
.csvtotable-table the <table>
.csvtotable-theme theme picker
.csvtotable-filters active-filter chip row
.csvtotable-chip one active filter, with -key, -value, and -remove parts
.csvtotable-clear the "clear all" control

A theme is nothing but a block of colour variables. Every rule in the stylesheet reads them, so a new theme is a copy of one block with different values — no rules to write and nothing else to touch:

[data-theme="my-theme"] {
  color-scheme: dark;      /* so scrollbars and dropdowns match */
  --ct-paper: #1a1b26;     /* page background */
  --ct-ink: #c0caf5;       /* body text */
  --ct-muted: #7f88b0;     /* labels, secondary text */
  --ct-rule: #232433;      /* row separators */
  --ct-rule-strong: #343b58;
  --ct-accent: #7aa2f7;    /* focus, active sort, filter chips */
  --ct-wash: #1f2335;      /* accent tint behind chips */
  --ct-hover: #1e2030;     /* row and control hover */
}

Switching themes is just swapping data-theme on <html>. Type and metrics sit outside the palettes in the --ct-text-* scale and --ct-sans/--ct-mono, since they do not vary by theme. Headings are styled by level (h1 to h6), so a Markdown heading in a description matches the same level elsewhere; start description headings at ## to keep one <h1> per page.

Nothing is styled through an ID, so a stylesheet loaded after the page's own <style> overrides any of the above with a single class selector. Classes beginning dt- come from DataTables and may change when it is upgraded.

Custom CSS and JavaScript

--css and --js inline a stylesheet and a script into the page, keeping the output a single self-contained file. Both take a file path:

csvtotable data.csv data.html --css brand.css --js setup.js

A leading @ is accepted too, for symmetry with --description, but means nothing here: --css @brand.css and --css brand.css are the same.

Placement is what makes them useful. The stylesheet goes last in <head>, after the built-in one, so a single class selector overrides anything above without !important. The script goes last in <body>, after the table is built, and CsvToTable.table holds the live DataTables API instance:

CsvToTable.table.order([2, "desc"]).draw();   // sort by the third column
CsvToTable.table.column(0).visible(false);    // hide the first column

The table's height is fitted on the next animation frame, so a script that measures layout should wrap the read in requestAnimationFrame. Column widths and the scroll height are set as inline styles, which a stylesheet cannot override — use --height for that.

A whole new palette is a stylesheet plus a matching --theme. The name does not have to be one of the built-ins as long as --css defines it, and the page's theme picker will list it alongside them:

csvtotable data.csv data.html --css custom.css --theme tokyonight

Selecting "Auto" in the picker unpins data-theme and falls back to the built-in light and dark palettes, so put anything that should survive that in :root or a class rule and keep [data-theme] blocks for the palette itself.

Both flags are trusted input: whatever the files contain runs for anyone who opens the page, so do not generate them from untrusted data. Content is escaped only so it cannot break out of its <style> or <script> element; it is not sanitised.

Run csvtotable --help for all options or csvtotable --version for the version. For compatibility with version 2, --caption, --display-length, --pagination, and --export still work; the last two disable those features.

Development

Building requires Go 1.25+ and Bun. Distribution packaging also requires Python and npm. table/dist is generated before the Go build and embedded in the final binary.

nix develop  # optional development environment
make build   # frontend and build/csvtotable
make test    # frontend, formatting, vet, and tests
make demo    # the published demo page under site/
make dist    # binary and host-platform packages under dist/
./build/csvtotable demo/meteorite-landings-1.csv demo/meteorite-landings-2.csv /tmp/meteorites.html

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

csvtotable-3.1.0b1-py3-none-win_amd64.whl (6.0 MB view details)

Uploaded Python 3Windows x86-64

csvtotable-3.1.0b1-py3-none-musllinux_1_2_x86_64.whl (5.9 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

csvtotable-3.1.0b1-py3-none-musllinux_1_2_aarch64.whl (5.4 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

csvtotable-3.1.0b1-py3-none-manylinux_2_17_x86_64.whl (5.9 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

csvtotable-3.1.0b1-py3-none-manylinux_2_17_aarch64.whl (5.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

csvtotable-3.1.0b1-py3-none-macosx_12_0_x86_64.whl (6.0 MB view details)

Uploaded Python 3macOS 12.0+ x86-64

csvtotable-3.1.0b1-py3-none-macosx_12_0_arm64.whl (5.6 MB view details)

Uploaded Python 3macOS 12.0+ ARM64

File details

Details for the file csvtotable-3.1.0b1-py3-none-win_amd64.whl.

File metadata

  • Download URL: csvtotable-3.1.0b1-py3-none-win_amd64.whl
  • Upload date:
  • Size: 6.0 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for csvtotable-3.1.0b1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 0296ac14c019bbe154d15a7ba125bdd42e95923456ad6e3a92628fb0b1186334
MD5 dbb8baabec53ac542575d3390038ff7c
BLAKE2b-256 9547c8cc6e1ccf365dda5fafe733b5b6369a1051d2944db347efe8a9350af437

See more details on using hashes here.

Provenance

The following attestation bundles were made for csvtotable-3.1.0b1-py3-none-win_amd64.whl:

Publisher: release.yml on vividvilla/csvtotable

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file csvtotable-3.1.0b1-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for csvtotable-3.1.0b1-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 876caf6ddad3c31d4c7cc27d93efdd3af05154f048408a702e37660f05478ba4
MD5 34c9a844911dd43c396a24d5850f45eb
BLAKE2b-256 91cda110c6f97c4f1f10590b66b3a478b58e722c3fc1e8911e5db6f0942b5766

See more details on using hashes here.

Provenance

The following attestation bundles were made for csvtotable-3.1.0b1-py3-none-musllinux_1_2_x86_64.whl:

Publisher: release.yml on vividvilla/csvtotable

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file csvtotable-3.1.0b1-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for csvtotable-3.1.0b1-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 aee0887cd57dc65c7d7fd08fb6d871d224645693313b8ad9e850aa9dbdd2d301
MD5 ede6143f4c523a9b7467553392f21a74
BLAKE2b-256 a881d9c26bbee46081670dfcd9ac4a3b869e57bf4dced3cf4d7e1fe8d15a472d

See more details on using hashes here.

Provenance

The following attestation bundles were made for csvtotable-3.1.0b1-py3-none-musllinux_1_2_aarch64.whl:

Publisher: release.yml on vividvilla/csvtotable

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file csvtotable-3.1.0b1-py3-none-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for csvtotable-3.1.0b1-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 d70b56ec8fbca39711858d733aaaaeffe6f37514e8fed3acb59024999a320d1e
MD5 6ce65b2cfabe5f43ce0a9d18b1b1ef51
BLAKE2b-256 6fe40d670b19c9abb25843013e3596a9d0b73da2ffbb409bd8c77b6e87011673

See more details on using hashes here.

Provenance

The following attestation bundles were made for csvtotable-3.1.0b1-py3-none-manylinux_2_17_x86_64.whl:

Publisher: release.yml on vividvilla/csvtotable

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file csvtotable-3.1.0b1-py3-none-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for csvtotable-3.1.0b1-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 6f6552297ed1022d22157540f0c60993ed847dc0bf762ac076ac48bece4bc7d6
MD5 046667ffc3049b4b9d339cb04b5c9634
BLAKE2b-256 1ea4e793c8393c5d5fff965d1f1cebfc4163c3ced427a3dc061e4759e00c5cd9

See more details on using hashes here.

Provenance

The following attestation bundles were made for csvtotable-3.1.0b1-py3-none-manylinux_2_17_aarch64.whl:

Publisher: release.yml on vividvilla/csvtotable

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file csvtotable-3.1.0b1-py3-none-macosx_12_0_x86_64.whl.

File metadata

File hashes

Hashes for csvtotable-3.1.0b1-py3-none-macosx_12_0_x86_64.whl
Algorithm Hash digest
SHA256 cd8814ef580c3889f271434390a3467b0e27e24b4ae45c3b9b0b9cbded929798
MD5 9145094b25aa6ae00af4b2500f82e6cf
BLAKE2b-256 0f0d35cbde0f277b667e1b8ac72afffadc5c6a5575c8e281acc439e18c269581

See more details on using hashes here.

Provenance

The following attestation bundles were made for csvtotable-3.1.0b1-py3-none-macosx_12_0_x86_64.whl:

Publisher: release.yml on vividvilla/csvtotable

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file csvtotable-3.1.0b1-py3-none-macosx_12_0_arm64.whl.

File metadata

File hashes

Hashes for csvtotable-3.1.0b1-py3-none-macosx_12_0_arm64.whl
Algorithm Hash digest
SHA256 4d9c4b9e4a8c992900b4a3cdddda2adef083bb326ba32f26d2cd601e286fc172
MD5 b7735ef263b4846274bae85e125b1914
BLAKE2b-256 942e1fd2a59cdbbce1b1047ec857d08026423ab23d47f9dfa540410c170c1ec3

See more details on using hashes here.

Provenance

The following attestation bundles were made for csvtotable-3.1.0b1-py3-none-macosx_12_0_arm64.whl:

Publisher: release.yml on vividvilla/csvtotable

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

3.2.0

7 files

3.1.0

7 files

This release

3.1.0b1 This release

7 files

3.0.0

7 files

2.1.1

2 files

2.1.0

2 files

2.0.0

2 files

1.1.4

1 file

1.1.3

2 files

1.1.2

2 files

1.1.1

2 files

1.1.0

2 files

1.0.2

2 files

1.0.1

2 files

1.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page