Rendering HTML and escaped text properly in rich text fields

shov
Member

I am observing an issue when pushing content to a rich text field (Contact field).

 

Behavior seems to vary depending on source.

  • Developer can push formatted html via integration
    • escaped character \n correctly results in a new line
    • however, reporting certain html tags like <a> are stripped
  • I can push formatted html via HubSpot API Playground
    • escaped characters result in "\n" rendered as text
    • however, my <a> html tags are fully preserved; links work correctly
    • I notice the API Playground automatically escapes characters like \n -> \\\n 

It looks like it's possible to send the html via integration.

 

Any tips or tricks to ensure content renders properly in the rich text field?

0 Upvotes
1 Accepted solution
RubenBurdin
Solution
Top Contributor

Hi @shov , this behavior is confusing but unfortunately pretty consistent once you know where the sanitization happens.

The key thing to know is that HubSpot rich text properties are HTML-first, but they still go through a server-side sanitizer that behaves slightly differently depending on how the request is constructed. Newlines (\n) are not a reliable formatting mechanism here.

 

The safest approach is to always send explicit HTML, especially <br> or <p> tags, rather than relying on escaped control characters. In practice, <br> is much more predictable than \n. The difference you’re seeing between your integration and the API Playground usually comes down to double escaping and middleware behavior.

 

The Playground sends a raw JSON body exactly as written, while many HTTP clients or frameworks will automatically escape strings, normalize newlines, or sanitize HTML before the request ever reaches HubSpot. That’s why you may see <a> tags preserved in the Playground but stripped when sent via your integration.

 

Another important nuance is that HubSpot strips certain tags or attributes if they don’t meet its allowlist. <a> is allowed, but attributes like target, rel, inline styles, or malformed URLs can cause the entire tag to be dropped. Always send fully qualified URLs and keep anchor tags very simple. This behavior is documented indirectly in the CRM properties API expectations (https://developers.hubspot.com/docs/api-reference/crm-properties-v3/guide )

 

So the practical rules of thumb are:

  • Send clean HTML, not escaped text.

  • Replace \n with <br> or wrap content in <p> tags.
  • Inspect the exact payload after your client library serializes it.

  • Avoid client-side sanitizers unless you explicitly control them.

If you can log the final JSON body right before the request is sent, that usually makes the root cause obvious very quickly.

Did my answer help? Please mark it as a solution to help others find it too.

Ruben Burdin Ruben Burdin
HubSpot Advisor
Founder @ Stacksync
Real-Time Data Sync between any CRM and Database
Stacksync Banner

View solution in original post

0 Upvotes
3 Replies 3
RubenBurdin
Solution
Top Contributor

Hi @shov , this behavior is confusing but unfortunately pretty consistent once you know where the sanitization happens.

The key thing to know is that HubSpot rich text properties are HTML-first, but they still go through a server-side sanitizer that behaves slightly differently depending on how the request is constructed. Newlines (\n) are not a reliable formatting mechanism here.

 

The safest approach is to always send explicit HTML, especially <br> or <p> tags, rather than relying on escaped control characters. In practice, <br> is much more predictable than \n. The difference you’re seeing between your integration and the API Playground usually comes down to double escaping and middleware behavior.

 

The Playground sends a raw JSON body exactly as written, while many HTTP clients or frameworks will automatically escape strings, normalize newlines, or sanitize HTML before the request ever reaches HubSpot. That’s why you may see <a> tags preserved in the Playground but stripped when sent via your integration.

 

Another important nuance is that HubSpot strips certain tags or attributes if they don’t meet its allowlist. <a> is allowed, but attributes like target, rel, inline styles, or malformed URLs can cause the entire tag to be dropped. Always send fully qualified URLs and keep anchor tags very simple. This behavior is documented indirectly in the CRM properties API expectations (https://developers.hubspot.com/docs/api-reference/crm-properties-v3/guide )

 

So the practical rules of thumb are:

  • Send clean HTML, not escaped text.

  • Replace \n with <br> or wrap content in <p> tags.
  • Inspect the exact payload after your client library serializes it.

  • Avoid client-side sanitizers unless you explicitly control them.

If you can log the final JSON body right before the request is sent, that usually makes the root cause obvious very quickly.

Did my answer help? Please mark it as a solution to help others find it too.

Ruben Burdin Ruben Burdin
HubSpot Advisor
Founder @ Stacksync
Real-Time Data Sync between any CRM and Database
Stacksync Banner
0 Upvotes
shov
Member

@RubenBurdin 6 out of 5 stars! Fantastic explanation.

 

I figured the source (integrations vs. playground) was probably contributing to the confusion. Your best practices make a lot of sense.

 

You mention keeping the <a> attributes simple. Ideally, my link would look something like this and open in a new window.

 

<a href="https://www.website.com/page.php?search=myterm" target="_blank">Link</a>

 

Would something like that be feasible?

0 Upvotes
SealaB
Community Manager
Community Manager

Hi @shov -

Welcome to the HubSpot Community!

I'm tagging @DanielPicklo and @Mike_Eastwood to see if they have insights into this specific behavior, as they often work with custom API integrations.
 

Because this is a rich text field, the API typically expects HTML formatting rather than relying on raw newline control characters. Try replacing your \n characters with <br> tags in your integration’s payload. This often resolves issues where line breaks are either ignored or displayed incorrectly.

Since the <a> tags work in the API Playground (which sends a raw JSON body) but are stripped or altered in your integration, also take a close look at the HTTP client, framework, or middleware you’re using. Some libraries automatically sanitize or escape HTML to prevent XSS attacks, which can result in tags being removed or turned into text.

Could you share a sanitized snippet of the exact JSON body your integration is sending (including headers if possible)? Seeing the real structure will make it easier to tell whether the HTML is being stripped, escaped, or malformed.

 

Let us know what you find!

Seala, Community Manager
0 Upvotes