Power Automate's Create HTML table action returns raw markup with no inline styles, no <tbody> wrapper, and unquoted attributes — a result that almost always needs cleanup before it renders reliably in an email body or a SharePoint page. The action is excellent at producing rows and cells from an array, but it deliberately skips presentation: there is no border-collapse rule, no cell padding, no alternating row colors, and no font sizing, because Power Automate expects you to add those yourself with downstream string concatenation or by including a <style> block in the same expression. Once that string reaches Outlook, Gmail, a Teams adaptive card fallback, or a SharePoint page, the receiving parser applies its own rules — and that is where formatting often goes wrong in production. A browser will quietly insert the missing <tbody>, lowercase the tag names, and quote the attributes. An email client may strip styles, drop an entire <style> block, or refuse to honor classes that target HTML attributes. To stop guessing what your recipients will actually see, you can preview exactly what the browser parser produces. The HTML Cleaner tool runs your fragment through DOMParser in text/html mode, serializes only body.innerHTML, and surfaces the normalized result in a read-only textarea. That gives you a deterministic picture of the normalized table before you paste it back into your flow or hand it to a designer.

What the Create HTML Table Action Actually Emits
The Create HTML table action takes an array, an optional set of columns, and a header label, and returns a single string containing the rendered table. The exact markup is functional rather than polished. By default, Power Automate emits a structure that resembles this pattern:
- Lowercase tags such as <table>, <thead>, <tbody>, <tr>, <th>, and <td>, which most browsers accept without complaint.
- Unquoted attributes on cells, especially style values that may contain width:100% or color expressions.
- No CSS at all unless you concatenate a <style> block or inline style="" attributes into the expression yourself.
- No closing tags for cells or rows in some edge cases, which a forgiving HTML parser will repair during rendering.
That output is correct enough that a browser can render it, but it is rarely what a designer wants. Most readers expect padding, borders, and a header background that visually separates the first row from the data rows. The typical workaround in Power Automate is to build a second string that wraps the action's output with a <style> block, a wrapping <div> with classes, or inline style attributes on every cell. None of those changes the underlying structure the parser will see — they only add declarations the parser has to honor.
Why Browser Normalization Changes the Output You Paste Back
Every consumer of your HTML string re-parses the markup before rendering. Outlook uses Word's HTML engine. Gmail applies its own sanitization rules. SharePoint relies on the browser DOM. That means the markup the parser produces is the markup your recipient sees, not the literal string Power Automate emitted. According to the WHATWG HTML Living Standard, the text/html parser is deliberately forgiving: it lowercases tag names, quotes attribute values, inserts implied elements such as <tbody>, and repairs some missing closing tags.
This is also where formatting inconsistencies sneak in. A style="width:100%" attribute Power Automate emits as style=width:100% will be quoted to style="width:100%" by any browser parser, which is what the recipient actually receives. A <TABLE> written in uppercase becomes <table>. A row that lost its closing tag during string manipulation is silently closed at the right boundary. The result is consistent across modern browsers because they share the WHATWG specification, but it can still differ from your source string in ways that matter for diffing, debugging, and downstream automation. Running the string through a parser preview before you commit it to an email action gives you the same result the recipient will get.
Normalize the Generated Table with HTML Cleaner
Before you commit a table string to an email action or a SharePoint HTTP request, run it through HTML Cleaner to see the exact body markup the browser would produce. The tool only normalizes; it never beautifies with indentation, never minifies, and never rewrites your CSS. The result is the body-only serialization of the parsed document.
- Copy the HTML string from your Create HTML table action (or the wrapped expression that adds your <style> block).
- Open HTML Cleaner and paste the fragment into the input area. Inputs above 500,000 UTF-16 code units are rejected before parsing, so trim large tables first.
- Decide whether to enable the Remove HTML comment nodes option. Power Automate templates sometimes ship with debugging comments — enable it to strip them, disable it to keep them.
- Normalize the input and read the output in the read-only textarea. The serialization is taken from body.innerHTML, so any <!DOCTYPE>, <head>, <title>, <meta>, and <link> content in your input is intentionally outside the result.
- Copy the complete result and, before pasting it back into Power Automate, decide whether the destination also requires a real HTML sanitizer. Normalization is not security; any <script>, onerror, or javascript: URL in your fragment survives untouched.
The output you copy is the body of a detached document produced by DOMParser.parseFromString in text/html mode. Scripts do not run during parsing, and no live preview is rendered, but the browser may still fetch resources referenced by <iframe> or <img> elements. If your table embeds remote images, expect those requests to fire from your browser when you normalize.
Table Fixes the Browser Parser Performs Automatically
The following comparison summarizes the most common normalizations you will see when you paste a Power Automate table string into HTML Cleaner. Use it as a checklist when reviewing the output.
| Source pattern in Power Automate output | What the browser parser produces |
|---|---|
| <TABLE> written in uppercase | <table> (lowercased by WHATWG tokenization) |
| Row content without an explicit <tbody> wrapper | An implied <tbody> inserted by the tree builder |
| style=width:100% (unquoted attribute) | style="width:100%" (quoted during serialization) |
| Cell or row with a missing closing tag | Repaired markup where the parser inferred the boundary |
| <!-- debug: iteration 7 --> left in the string | Removed when the comment-removal option is enabled; preserved otherwise |
These fixes are deterministic across modern browsers because every renderer follows the WHATWG HTML Living Standard. They are not a guarantee that your recovered structure matches what you typed — malformed input is repaired rather than rejected with an XML-style error — but they are reliable enough that the output of HTML Cleaner is a faithful preview of the recipient's DOM.
When You Still Need a Destination-Aware Sanitizer
Normalization changes how the markup is written; it does not change what the markup is allowed to do. The HTML Cleaner contract is explicit: scripts, event-handler attributes, javascript: URLs, <iframe>, forms, inline styles, data attributes, and unknown elements are all preserved exactly as parsed. If your Power Automate flow is rendering user-supplied content — SharePoint list column values, form responses, comments — the string you normalize is still dangerous when pasted into an active page or email body.
For those cases, pair HTML Cleaner with a destination-aware HTML sanitizer. Outlook, SharePoint, Teams, and a public website all have different policies, and a sanitizer configured for one of them will not be correct for the others. The right pattern is: normalize first to see what the parser produces, then sanitize against the rules of the destination, then deliver. The browser's innerHTML reference documents the same risk: fragment serialization is for inspection, not for safe publication.
If you also need to send the table's structured data downstream as JSON — for example, into a Dataverse row or a Logic App array — the companion guide on turning an HTML table into JSON for Power Automate covers the parsing side that this article does not.
Quick Checklist Before Pasting Output Back Into Power Automate
Run through this list every time you copy a normalized table string out of HTML Cleaner and back into a flow:
- Confirm the output is not empty. An empty body after parsing or comment removal is a valid zero-length result, but it usually means your input was malformed beyond repair.
- Confirm the output is below the 1,000,000 UTF-16 code-unit boundary. HTML Cleaner refuses them with an explicit message rather than slicing.
- Spot-check that your <style> block survived. Inline CSS and style elements are preserved by normalization, so classes targeting HTML elements should still match.
- Re-run with the comment-removal option flipped if your downstream template depends on conditional comments for Outlook (<!--[if mso]>).
- If the table is going into an email body, hand the normalized output to a destination-aware sanitizer before the final Send an email action. Normalization alone does not protect against active content.
Following that loop turns the Create HTML table action's minimal output into a deterministic string you can trust, while keeping presentation choices entirely in your hands. The browser parser handles the boring repairs; HTML Cleaner shows you what it did; and the rest of your flow stays focused on styling, sanitization, and delivery.
If you're weighing options, How to Edit an HTML Web Page Step by Step covers this in detail.