Skip to main content

API and JSON Exploration

VisiData can consume JSON from any source — local files, piped curl output, or JSONL streams. Nested fields expand interactively with (. This makes VisiData a fast, zero-code alternative to jq for exploratory API work.

Learning Focus

The core pattern: curl -s URL | vd -f json → expand nested ( → filter | → export Ctrl+S. Once you know this loop, any API response becomes an interactive sheet.


Sample API-Style JSON

mkdir -p ~/github/practice-folder/visidata/07-api

cat > ~/github/practice-folder/visidata/07-api/01-github-repos.json << 'EOF'
[
{"id": 1, "name": "visidata", "owner": {"login": "saulpw"}, "stargazers_count": 7200, "language": "Python", "archived": false},
{"id": 2, "name": "datasette", "owner": {"login": "simonw"}, "stargazers_count": 9100, "language": "Python", "archived": false},
{"id": 3, "name": "csvkit", "owner": {"login": "wireservice"}, "stargazers_count": 5800, "language": "Python", "archived": false},
{"id": 4, "name": "old-tool", "owner": {"login": "user99"}, "stargazers_count": 120, "language": "Shell", "archived": true}
]
EOF

Open JSON from a Local File

vd ~/github/practice-folder/visidata/07-api/01-github-repos.json

Initial view — nested columns appear as {...}:

id name owner stargazers_count language archived
1 visidata {...} 7200 Python False
2 datasette {...} 9100 Python False
3 csvkit {...} 5800 Python False
4 old-tool {...} 120 Shell True

Pipe Live from an API

curl -s https://api.github.com/repos/saulpw/visidata | vd -f json

Or for a list endpoint:

curl -s "https://api.github.com/search/repositories?q=visidata&per_page=10" | vd -f json
note

GitHub API returns a JSON object with a items key containing the list. Navigate with Enter on the items column to open the list as a new sheet.


Expand Nested Columns

The owner column shows {...} — expand it:

# Move cursor to 'owner' column
(
# Expands one level: owner.login, owner.id, etc. appear as new columns

After expanding:

id name owner.login stargazers_count language archived
1 visidata saulpw 7200 Python False
2 datasette simonw 9100 Python False

For deeply nested JSON:

# Expand all nested columns one level deep
g(

# Expand to depth 2
z( 2

Collapse expanded columns:

) # collapse current expanded column
g) # collapse all

Cast and Analyze

# Cast stargazers_count to int
# Move to 'stargazers_count' column → press #

# Sort by stars descending
]

Result — most-starred repos first:

name owner.login stargazers_count language
datasette simonw 9100
visidata saulpw 7200
csvkit wireservice 5800
old-tool user99 120

Filter Results

# Filter out archived repos
z|
# Enter: archived == False

# Open filtered sheet
"

Frequency Table on Language

# From filtered sheet, move to 'language' column
Shift+F

Result:

language count percent
Python 3 100%

Export Results

# Export the filtered, expanded sheet
Ctrl+S
# Enter: ~/github/practice-folder/visidata/07-api/active-repos.csv

Complete API Workflow

curl -s <API_URL> | vd -f json

1. ( on nested column → expand owner.login
2. # on numeric column → cast to int (stargazers_count)
3. ] → sort by stars descending
4. z| archived == False → " → filter to active repos
5. Shift+F on language → language distribution
6. Ctrl+S → export as CSV

Troubleshooting

ProblemCauseFix
JSON opens as single text columnNot valid JSONValidate with echo "$json" | python3 -m json.tool
Nested columns don't expandColumn type is string, not dictEnsure response is parsed as JSON (-f json)
API returns paginated dataSingle page onlyLoop curl and concat with jq -s '.[0] + .[1]'
Rate limit error from APIToo many requestsUse --max-rows to sample; add auth header with -H

Hands-On Practice

vd ~/github/practice-folder/visidata/07-api/01-github-repos.json

# 1. View the sheet — notice owner column shows {...}
# 2. Move to 'owner' column → press ( → owner.login appears
# 3. Move to 'stargazers_count' → press # → cast to int
# 4. Press ] → sort by stars descending
# 5. Press z| → Enter: archived == False → select active repos
# 6. Press " → open filtered sheet
# 7. Move to 'language' → Shift+F → see language breakdown
# 8. Press q → back to filtered sheet
# 9. Press Ctrl+S → save as /tmp/active-repos.csv

What's Next