Export Trello cards to Google Sheets with the API, including the list and member IDs that need translating and the CSV export free plans do not get.
Trello's CSV export is a paid feature, so on free and Standard workspaces the API is not a power-user option, it is the only practical route to a spreadsheet. The good news is that it is one of the simpler APIs here. The one thing to plan for is that cards reference lists and members by ID, so a raw export is full of opaque strings unless you fetch the board's lists and members and translate them.
The paid option: CSV export
On Premium or Enterprise, open the board menu and choose Print, export and share → Export as CSV, then import into Sheets. On free and Standard workspaces only JSON export is offered, which is a raw dump rather than a table and needs processing before it is useful in a spreadsheet.
Trello to Google Sheets for free (Apps Script + API)
Get an API key from trello.com/app-key and generate a token from the manual authorisation link on that page. Both are passed as query parameters. The board ID is in the board URL, or you can call the boards endpoint to list them.
The approach that keeps this fast: fetch lists and members once per board, build lookup maps, then fetch all cards in a single call. Trello returns every card on a board in one response, so per-card requests are rarely necessary and are the main way people hit rate limits.
function importTrelloBoard() { const KEY = "YOUR_API_KEY"; const TOKEN = "YOUR_TOKEN"; const BOARD = "YOUR_BOARD_ID"; const auth = "key=" + KEY + "&token=" + TOKEN; const base = "https://api.trello.com/1/boards/" + BOARD; const get = (path, extra) => JSON.parse(UrlFetchApp.fetch( base + path + "?" + auth + (extra ? "&" + extra : ""), { muteHttpExceptions: true } ).getContentText()); // Cards reference lists and members by ID, so build lookups first. const listNames = {}; get("/lists").forEach((l) => { listNames[l.id] = l.name; }); const memberNames = {}; get("/members").forEach((m) => { memberNames[m.id] = m.fullName || m.username; }); // Custom fields need customFieldItems=true, and their definitions live // separately because cards only carry field and option IDs. const fieldNames = {}, optionNames = {}; get("/customFields").forEach((f) => { fieldNames[f.id] = f.name; (f.options || []).forEach((o) => { optionNames[o.id] = o.value.text; }); }); // One call returns every card on the board. const cards = get("/cards", "customFieldItems=true"); const rows = cards.map((c) => { const custom = (c.customFieldItems || []).map((item) => { const name = fieldNames[item.idCustomField] || "field"; const value = item.idValue ? optionNames[item.idValue] : item.value && (item.value.text || item.value.number || item.value.date); return name + ": " + (value || ""); }).join("; "); return [ c.name, listNames[c.idList] || c.idList, (c.idMembers || []).map((id) => memberNames[id] || id).join(", "), (c.labels || []).map((l) => l.name || l.color).join(", "), c.due || "", c.dueComplete, c.dateLastActivity, custom, c.shortUrl, ]; }); const header = ["Card","List","Members","Labels","Due","Done", "Last activity","Custom fields","URL"]; const ss = SpreadsheetApp.getActiveSpreadsheet(); const sheet = ss.getSheetByName("Trello") || ss.insertSheet("Trello"); sheet.clearContents(); sheet.getRange(1, 1, 1, header.length).setValues([header]); if (rows.length) { sheet.getRange(2, 1, rows.length, header.length).setValues(rows); }}Run once to authorise, then add a time-driven trigger. Note that the cards endpoint returns open cards by default; archived ones need filter=all, which matters when you are measuring completed throughput rather than current state.
Limits: around 300 requests per 10 seconds per key and 100 per token, which board-level calls stay well inside. Very large boards return large responses, so request only the fields you need with the fields parameter if responses get unwieldy.
The Brooked method
Brooked resolves list, member, label and custom-field IDs to names automatically, so cards arrive as a readable table rather than a grid of identifiers. It works the same on free workspaces as paid ones, since it uses the API rather than the CSV export, and several boards can import into one spreadsheet on a single schedule.
Step 1: Install Brooked
Install Brooked from the Google Workspace Marketplace. Free tier includes 100 imports per month, no credit card required.
Step 2: Connect Trello
Choose Trello in Brooked and authorise your account. Pick the boards you want, choose whether to include archived cards, and import.
Step 3: Schedule the refresh
Set the import to re-run daily or weekly. Because Trello itself keeps no history of how a board looked last week, a scheduled snapshot is the simplest way to build trend data on throughput and cycle time.
Method comparison
| Method | Cost | Setup | Refresh | Two-way | Best for |
|---|---|---|---|---|---|
| Trello CSV export | Paid plans only | 2 min | Manual | No | One-off export on Premium or Enterprise |
| Apps Script + Trello API | Free | 20 to 30 min | Time-driven trigger | DIY | Free plans, and any board, no budget |
| Power-Ups and Butler | Free tier limited · paid for volume | 5 to 15 min | On card change | Varies | Reacting to individual card events |
| Brooked | Free tier · Pro $29/user/mo | ~3 min | Scheduled (hourly, daily, weekly) | Yes | Scheduled board reporting across boards |
Common use cases
- Board snapshots: count cards per list over time to see whether work is piling up
- Cycle time: track how long cards sit in each stage using scheduled snapshots
- Workload: cards per member across several boards in one table
- Client reporting: share a filtered view of a board without giving board access
- Cross-board portfolio: combine multiple team boards into one status report
Troubleshooting common issues
Related Articles
- How to Connect Monday.com to Google Sheets
- How to Connect Clockify to Google Sheets
- How to Connect ClickUp to Google Sheets
Frequently asked questions
Can I export a Trello board to CSV on the free plan?
No. CSV export is a paid feature, available on Premium and Enterprise; free and Standard workspaces only offer JSON export, which is not something you can drop straight into Sheets. This is the usual reason free-plan users go to the API, which has no such restriction and works on every plan.
Why do my Trello cards show idList instead of the list name?
Cards reference their list by ID, not name, so a card export gives you values like 5f2b8c9d1e4a3b2c1d0e9f8a. Fetch the board's lists separately from the lists endpoint, build an ID-to-name map, and translate as you write rows. The same applies to members, which come back as an idMembers array of member IDs.
How do I get my Trello API key and token?
Generate a key from the Trello developer page at trello.com/app-key, then use the manual token link on that same page to authorise a token for your own account. Both go on the query string of every request as key and token. Treat the token like a password: it carries your full account access unless you scope it.
Why are my custom fields missing?
Custom fields are not returned with cards by default. Add customFieldItems=true to the request to include them, and fetch the board's custom field definitions separately, because the items on each card reference field IDs and option IDs rather than carrying names and labels.
What are Trello's rate limits?
Roughly 300 requests per 10 seconds per API key, and 100 per 10 seconds per token. Board-level endpoints return all cards in one call, so a normal import stays well inside these. You are most likely to hit them when looping per-card requests, which is a good reason to prefer board-level calls with nested parameters.
Can I write back to Trello from Google Sheets?
Yes for editable card fields, and Brooked supports write-back, so you can bulk-update due dates, list placement or labels from a sheet. Some values are derived and not writable, including dateLastActivity and the card's shortLink.
Connect Trello to Google Sheets today.
Free tier: 100 imports per month, no credit card required. Or see the full Trello integration details.
Install Brooked free →

