tabulate
Pretty-print tabular data in Python — formats lists of lists, dicts, and named tuples as ASCII tables in dozens of formats. tabulate features: tabulate() function accepting list-of-lists, list-of-dicts, dict-of-lists, numpy arrays, pandas DataFrames, headers= for column names, tablefmt for output format (plain, simple, grid, pipe, orgtbl, rst, mediawiki, html, latex, tsv, github, rounded_outline), floatfmt for number formatting, intfmt, stralign for text alignment, numalign for number alignment, showindex for row numbers, and colalign for per-column alignment.
Score Breakdown
⚙ Agent Friendliness
🔒 Security
Pure formatting library. tablefmt='html' escapes values by default — safe for user-provided data. tablefmt='unsafehtml' passes HTML through unescaped — only use with trusted data to prevent XSS. No network calls or security concerns beyond XSS in HTML output.
⚡ Reliability
Best When
CLI scripts and quick tabular output where rich is overkill — tabulate provides dozens of table formats with a single simple function call.
Avoid When
Large datasets, colored/styled output (use rich.Table), or pandas DataFrames (use built-in methods).
Use Cases
- • Agent CLI table — from tabulate import tabulate; data = [['Alice', 30, 'NYC'], ['Bob', 25, 'LA']]; headers = ['Name', 'Age', 'City']; print(tabulate(data, headers=headers, tablefmt='simple')) — simple table; agent prints formatted table in CLI output; tablefmt='simple' for plain ASCII; tablefmt='grid' for bordered table
- • Agent dict table — data = [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]; print(tabulate(data, headers='keys')) — dict rows; agent prints list-of-dicts; headers='keys' auto-extracts column names from dict keys; headers='firstrow' for first row as header
- • Agent markdown table — md = tabulate(data, headers=headers, tablefmt='pipe'); print(md) — GitHub markdown; agent generates markdown table for documentation, GitHub README, or Notion; tablefmt='pipe' produces: | Name | Age |\n|------|-----|\n| Alice | 30 |
- • Agent HTML table — html = tabulate(data, headers=headers, tablefmt='html') — HTML table; agent generates HTML table for email, web, or report; tablefmt='unsafehtml' for raw HTML in cells; default html escapes cell values
- • Agent number formatting — data = [['π', 3.14159265], ['e', 2.71828]]; print(tabulate(data, headers=['Symbol', 'Value'], floatfmt='.3f')) — '3.142', '2.718'; agent formats floats uniformly; intfmt=',' for thousand separator on integers; per-column: floatfmt=('.3f', '.2f')
Not For
- • Large datasets — tabulate builds entire table in memory; for large datasets use pandas to_string() or streaming formatters
- • Rich terminal formatting — for colored, styled tables use rich.Table which supports colors and Unicode box-drawing
- • Pandas DataFrames — pandas has built-in .to_string(), .to_markdown(), .to_html() — no need for tabulate
Interface
Authentication
No auth — table formatting library.
Pricing
tabulate is MIT licensed. Free for all use.
Agent Metadata
Known Gotchas
- ⚠ headers='keys' only works for list-of-dicts — tabulate(data, headers='keys') extracts keys from first dict; if data is list-of-lists: use headers=['Col1', 'Col2'] explicitly; if data is dict-of-lists: headers='keys' extracts dict keys as column names; agent code: check data format before setting headers
- ⚠ Cell values must be string-representable — None becomes empty string; objects use str() representation; agent code with complex objects: convert to string before tabulating: [[str(x) for x in row] for row in data]; tabulate does not call repr() — uses str()
- ⚠ Column width is determined by widest cell — long cell values widen entire column; for truncation: agent code must truncate values before passing to tabulate: str(val)[:50] for each cell; tabulate has no built-in truncation or wrapping
- ⚠ tablefmt='html' escapes HTML by default — cell values with < > & are escaped to < > &; tablefmt='unsafehtml' skips escaping; agent code generating HTML: use default html for user data (security); use unsafehtml only for known-safe HTML content
- ⚠ Mismatched row lengths produce ragged table — [[1, 2, 3], [4, 5]] produces table with empty cell; tabulate pads shorter rows with empty strings; agent code: ensure uniform row length or use dicts which handle missing keys gracefully
- ⚠ floatfmt applies to all float columns — tabulate(data, floatfmt='.2f') applies to every float; for per-column formatting: floatfmt=('.2f', '.4f') as tuple matching column count; agent code mixing precision: use tuple format; or pre-format floats as strings before passing to tabulate
Alternatives
Full Evaluation Report
Detailed scoring breakdown, competitive positioning, security analysis, and improvement recommendations for tabulate.
Scores are editorial opinions as of 2026-03-06.