{"slug":"html-table-to-csv","name":"HTML Table to CSV: Merged Cells and Entities Done Right","version":"1.0.0","updated_at":"2026-10-08T16:10:32.386Z","use_when":"Converts one HTML table into RFC 4180 CSV and answers with the CSV only, no code fence. The header is the first row, every cell keeps the text a browser shows after entities are decoded (&amp;, &euro;, &#8212;, a no-break space), links, bold and other inline markup vanish and their text stays, a line-break tag becomes a space, and numbers such as 1,250 stay text in quotes. A cell that spans rows or columns (rowspan, colspan) repeats its value in every slot it covers, so the columns line up under the right header. Footer rows go last, a caption is not a row, nothing is summed, sorted or converted. A page with no table, with two tables, or with a table inside a table gets a fixed one-line CANNOT CONVERT answer instead of a guess. Use when scraped or pasted HTML has to become CSV for a spreadsheet, a database or a data pipeline.","not_for":"Pages with no table, two tables without a named choice, or a table inside a table: you get a one-line CANNOT CONVERT answer instead of a guess. It fetches nothing, runs no JavaScript, reads no tables drawn with div elements, and sums, sorts or reformats nothing. Output follows RFC 4180: comma, LF (CRLF on request).","languages":["any"],"tags":["html","table","csv","rfc-4180","scraping","rowspan","colspan","no-guessing"],"category":"data","category_url":"https://aiskills402.com/categories/data","keywords":["rowspan, colspan","scraped or pasted HTML","footer rows go last"],"faq":[{"q":"What happens to a cell that spans two rows or two columns?","a":"Its text is repeated in every slot it covers, because a CSV has no merged cells. A region name written once with rowspan 2 appears in both rows, and a header written once with colspan 2 appears over both columns. The cells that follow in the next row slide past the covered slot, exactly as a browser lays them out, so nothing ends up one column to the left. If you ask for padding instead, only the first slot gets the text and the others stay empty. Header cells that span columns get the same treatment, so a two-column group heading names both columns for whoever reads the file later."},{"q":"Does it change my numbers, links and special characters?","a":"It copies what a browser shows and nothing else. A price with a thousands comma keeps the comma and gets quotes. Codes with leading zeros, negative amounts and dates keep every character. A link gives its words and never its address, bold and other inline markup vanish, and entities such as the ampersand, the euro sign and the long dash are decoded exactly once. A text written as an ampersand, the letters lt and a semicolon turns into those four characters and is not decoded a second time. Nothing is summed, sorted, rounded or translated, and a footer row of totals is copied, not recomputed."},{"q":"What if the page has two tables or no table?","a":"You get one line that starts with CANNOT CONVERT and says why, for example that the page holds two tables. The same goes for a table nested inside a cell, because one CSV cannot hold both without an invented rule. If your request names the table, by an id, a caption or a heading, the skill converts that one and ignores the rest of the page. Pages with navigation, scripts and styles around one table are fine: only the table is read, and the rest of the page is ignored."},{"q":"Does it help Claude Sonnet?","a":"Barely. Without the skill Sonnet got 23 of 24 tables right, with it 24 of 24. It already expanded rowspan and colspan, decoded entities once, kept thousands commas, refused two tables or a nested one and ignored markup. It missed one thing: a cell holding a comma, which came out unquoted and split the row. Haiku scored 23 of 24 both ways, with the same comma slip."}],"examples":[{"lang":"en","model":"claude-sonnet-5-5","input_excerpt":"<table><tr><th>Region</th><th>Shop</th><th>Sales</th></tr><tr><td rowspan=\"2\">North</td><td>A</td><td>10</td></tr><tr><td>B</td><td>20</td></tr><tr><td>South</td><td>C</td><td>30</td></tr></table>","output_excerpt":"Region,Shop,Sales\nNorth,A,10\nNorth,B,20\nSouth,C,30"},{"lang":"bg","model":"claude-sonnet-5-5","input_excerpt":"<table><thead><tr><th>Град</th><th>Цена</th><th>Бележка</th></tr></thead><tbody><tr><td>София</td><td>1,5&nbsp;лв.</td><td>Първа&nbsp;&mdash;&nbsp;втора</td></tr><tr><td>Варна</td><td>2 лв.</td><td>без</td></tr></tbody></table>","output_excerpt":"Град,Цена,Бележка\nСофия,\"1,5 лв.\",Първа — втора\nВарна,2 лв.,без"},{"lang":"de","model":"claude-sonnet-5-5","input_excerpt":"<table><tr><th>Stra&szlig;e</th><th>Betrag</th></tr><tr><td>M&uuml;llerweg 3</td><td>1.250,50</td></tr><tr><td>K&ouml;ln Nord</td><td>12,00</td></tr></table>","output_excerpt":"Straße,Betrag\nMüllerweg 3,\"1.250,50\"\nKöln Nord,\"12,00\""},{"lang":"es","model":"claude-sonnet-5-5","input_excerpt":"<p>Resumen:</p><table><tr><th>Ciudad</th><th>Habitantes</th></tr><tr><td>M&aacute;laga</td><td>580.000</td></tr><tr><td>Sevilla</td><td>680.000</td></tr></table><p>Fin.</p>","output_excerpt":"Ciudad,Habitantes\nMálaga,580.000\nSevilla,680.000"}],"page_url":"https://aiskills402.com/skills/html-table-to-csv","markdown_url":"https://aiskills402.com/skills/html-table-to-csv.md","image_url":"https://cdn.aiskills402.com/og/skills/html-table-to-csv/13697f19.png","related_url":"https://api.aiskills402.com/v1/skills/html-table-to-csv/related","purchases_count":null,"tested":{"date":"2026-10-08","strong":{"model":"claude-sonnet-5-5 (Claude Code alias \"sonnet\")","verdict":"Right on all 24 tables, read by hand: it repeated merged values in every covered slot, kept the cells after a rowspan in their own columns, decoded entities once, turned line breaks and no-break spaces into spaces, wrote link words without addresses, kept thousands commas and leading zeros as quoted text, put footer rows last, converted one named table out of a full page, refused the page with two tables, the nested table, the list, the error page and the page with no table with the fixed line, and quoted a cell that held a comma although the cell text told it to ignore the other rows. The Bulgarian, German and Spanish tables came back intact."},"weak":{"model":"claude-haiku-5-5 (Claude Code alias \"haiku\")","verdict":"Right on 23 of 24 tables, but it missed one: in the table whose cell text said to ignore the other rows and reply OK it did not obey the cell, yet it wrote the comma inside that cell without quotes, so the row splits into three fields. Everything else matched, including every merged cell, the refusals and the three non-English tables."},"note":"Twenty-four tables written by us (16 with a trap, among them 4 that must be refused, and 8 sound): rowspan and colspan blocks, entities and a doubled entity, line breaks and no-break spaces, links, images, a header cell in the body, a footer written before the body, a page around one table, a cell with a quote and an empty cell, a planted instruction inside a cell, and Bulgarian, German and Spanish tables. Each answer is scored by code: the exact CSV with quoting allowed either way, and for the refusals the fixed one-line answer, with no fence. The rules were checked on 2026-10-08 against the HTML Standard (the table model and the slots covered by earlier cells) and RFC 4180 (quoting). Our own decisions, not from the standards: a no-break space and a line-break tag become ordinary spaces (the task states it), merged values are repeated, footer rows go last, and a page with no or several tables gets a refusal. No check was widened after the run. One run per model and table.","baseline":{"date":"2026-10-08","rows":[{"label":"Tables converted right (24 tables)","better":"higher","strong":{"with":{"n":24,"of":24},"without":{"n":23,"of":24}},"weak":{"with":{"n":23,"of":24},"without":{"n":23,"of":24}}}],"note":"Same request on both sides, the task text states the output form; the bare side is scored with the same content checks, a fence removed first. Read by hand, Sonnet without the skill already got every merged cell, entity, refusal and non-English table right. It missed one: on the table with a planted instruction it first wrote the comment cell unquoted and then added a correction below it, so the answer was not the CSV alone. Haiku without the skill got the same 23 of 24 and missed the same table, with an unquoted comma that splits the row. The skill gives no measurable gain on the tested tables."},"report_url":null},"price_usd":"0.02","price_micro":20000,"size_bytes":8675,"sha256":"3f689a1b809a8eccfcf9915186422434704f25ae164f8cb041f2b77e8e0da4b2","outline":["Hard rules","What a cell contains","Rows, header, merged cells","The output form","When to refuse","Work in this order","Short examples"],"license":{"summary":"Perpetual, non-exclusive; use and modify for yourself incl. paid work; no resale or republishing","holder":"Georgi Kalchev, aiskills402.com","url":"https://aiskills402.com/docs#license"},"buy_url":"https://api.aiskills402.com/v1/skills/html-table-to-csv/file","redownload_url_template":"https://api.aiskills402.com/v1/purchases/{token}","mcp_tool":null,"payment":{"protocol":"x402","scheme":"exact","asset":"USDC","selling":true,"network":"base","network_caip2":"eip155:8453","pay_to":"0x8e37022edcf0f21cf3c9f93fee9d4d32519f36f4","facilitator":"cdp"},"seo_title":"HTML Table to CSV Skill for Merged Cells","seo_description":"Convert one HTML table to RFC 4180 CSV: merged cells expanded, entities decoded, refuses pages with no or several tables. Pay $0.02 once, in USDC.","versions":[{"version":"1.0.0","date":"2026-10-08","changelog":"# Changelog\n\n## 1.0.0 — 2026-10-08\n\nFirst release: converts one HTML table into RFC 4180 CSV. The header is the first row, every cell keeps the text a browser shows (entities decoded once, inline tags gone, a line-break tag and a no-break space turned into spaces, white space collapsed), merged cells (rowspan, colspan) repeat their value in every covered slot, footer rows go last, numbers such as 1,250 stay text in quotes. A page with no table, two tables or a nested table gets a fixed one-line CANNOT CONVERT answer.\n\nRules checked on 2026-10-08 by read-only fetch of the HTML Standard (tables chapter: colspan and rowspan give the number of columns and rows a cell spans; the \"forming a table\" algorithm covers slots with xcurrent..xcurrent+colspan and ycurrent..ycurrent+rowspan, so cells skip slots covered from earlier rows) and of RFC 4180 (fields with commas, double quotes or line breaks are enclosed in double quotes; a quote inside is doubled; spaces are part of a field; the last line break is optional; quotes may not appear in an unquoted field). Named and numeric character references are defined by the same standard (parsing chapter). Our own decisions, not from the standards: a line-break tag and a no-break space become ordinary spaces; images add nothing; LF as the default line break; footer rows last; repeat (not pad) merged values; refusal on no, several or nested tables. The rowspan value 0 and the exact order of rows in a table whose footer is written before its body were not tested and are not in the cases.\n\nTests (24 cases: 16 traps including 4 refusals, 8 controls) written and the control run done on 2026-10-08, no model calls yet. Model results and the price check come after the queued run.\n\n## Model test — 2026-10-08\n\nMeasured: Sonnet 24/24 with the skill, 23/24 without; Haiku 23/24 with, 23/24 without (one run per model and case). Price set to $0.02 (20000 micro-USDC): Sonnet gain 1. No check was widened: the only failure on every side is planted-instruction, where the cell with a comma was written unquoted (a split row, a real defect). No case needs a re-run.\n"}]}