BeautifulSoup: Why prettify() Changes Your HTML Description (Use decode() Instead)
BeautifulSoup's soup.prettify() inserts newlines and indentation that can alter how an HTML description renders and is stored. Use soup.decode() (or str(soup)) for a faithful copy. Here's why.
Long Nguyen
Fullstack Developer · AI Engineer · Researcher
When you process an HTML product description with BeautifulSoup and write the result back, the method you use to serialize the soup matters. soup.prettify() and soup.decode() both turn a parse tree into a string, but they are not interchangeable: prettify() can silently change how the description renders and what gets stored, while decode() gives you a faithful copy.
The difference
soup.decode() is the compact serializer — it's exactly what str(soup) calls under the hood. It returns the HTML as-is, without adding any cosmetic whitespace. soup.prettify() is the same serialization machinery with pretty-printing turned on: it puts each tag on its own line and adds indentation so the markup is easy for a human to read. That readability comes from inserting newline (\n) and space characters into the output that were never in the original.
Why prettify() changes the description
Those inserted characters aren't always cosmetic once rendered. When prettify() breaks an inline element onto its own line, the newline and indentation between that element and the surrounding text collapse — in a browser — into a single space. That space wasn't there before.
Original:
<p>Size: <b>Large</b>. Ships free.</p>
After prettify():
<p>
Size:
<b>
Large
</b>
.
Ships free.
</p>
The original renders as "Size: Large. Ships free." The prettified version renders as "Size: Large . Ships free." — a stray space now sits before the period, because the newline between </b> and . became whitespace. Multiply that across every inline tag (<a>, <span>, <em>, <strong>) in a rich description and the rendered text drifts from the original.
It gets worse if the stored description is ever displayed in a whitespace-preserving context — inside <pre>, a <textarea>, an element with white-space: pre, or when a downstream system treats it as plain text. There, every newline and indentation space prettify added shows up literally.
What to use
- To read, modify, and write an HTML description back, use
str(soup)orsoup.decode(). It round-trips the markup without introducing whitespace. - Use
soup.prettify()only for human inspection — logging, debugging, or eyeballing structure — never for the value you persist or re-submit. - If you already stored prettified descriptions, don't assume they're clean: they may carry inline-boundary spacing changes that a re-parse won't automatically undo.
The rule of thumb: prettify() is for your eyes, decode() is for your data.
Cleanly normalizing HTML descriptions across marketplaces is a surprisingly easy place to introduce subtle rendering bugs like this. Having built multi-channel integrations across 20+ sales channels, I deal with description sanitization and HTML round-tripping regularly. If you need help with eCommerce support or marketplace API integration, check out Netalith's eCommerce support service or reach out to me directly on LinkedIn.
FAQ
Frequently asked questions
What is the difference between soup.prettify() and soup.decode()?
decode() (what str(soup) calls) serializes the HTML faithfully with no added whitespace. prettify() is the same serializer with pretty-printing on, so it inserts newlines and indentation for readability.
Why does prettify() change how my description looks?
When prettify() puts an inline element on its own line, the newline and indentation around it collapse into a single space in the browser. That adds spaces — for example before a period after a bold word — that weren't in the original.
Which one should I use to save an HTML description?
Use str(soup) or soup.decode(). They round-trip the markup without adding cosmetic whitespace. Reserve prettify() for debugging and human inspection only.
Can prettified whitespace ever show up literally?
Yes. If the description is rendered in a whitespace-preserving context like a pre tag, a textarea, or with white-space: pre, or is treated as plain text downstream, every newline and space prettify added appears literally.