How to Format WhatsApp API Messages with Bold, Italics, and Line Breaks

You just sent an automated invoice or order update through the WhatsApp Business API. Instead of a clean, structured message with bold headings and neat line breaks, your customer received a single, unreadable block of text cluttered with raw backslash-n characters and literal asterisks.
Formatting errors make automated systems look broken. When customers in Pakistan or India receive transaction updates, utility bills, or delivery alerts, readability directly impacts your support volume. If they cannot read the bill amount or the tracking number at a glance, they will call your support desk. Let us look at how the WhatsApp Business API actually parses text formatting, how to handle line breaks in JSON payloads, and why your templates might be failing.
The Rules of WhatsApp Markdown
WhatsApp uses a simplified version of Markdown for text styling. While this works seamlessly in the consumer app, implementing it programmatically through the API requires strict adherence to syntax rules. The API parses four primary formatting styles:
- Bold: Wrap the text in asterisks. For example: *text*
- Italics: Wrap the text in underscores. For example: _text_
- Strikethrough: Wrap the text in tildes. For example: ~text~
- Monospace: Wrap the text in three backticks. For example: ```text```
You can combine these styles to create bold-italic text. To do this, wrap the text in both underscores and asterisks: _*bolditalic*_. The order of the characters must match on both sides. If you start with an underscore and then an asterisk, you must close with an asterisk and then an underscore.
The most common reason API-generated formatting fails is incorrect spacing. WhatsApp's parsing engine is sensitive to spaces relative to the formatting characters. For example, writing * text * with spaces inside the asterisks will fail to render as bold. It will display the literal asterisks to the user. The formatting character must touch the first and last letters of the formatted string directly. Writing *text* works; writing *text * or * text* does not.
Punctuation can also disrupt formatting. If you write *text.* with a period inside the asterisk, it renders correctly. If you write *text*, with a comma outside, it also renders correctly. However, wrapping punctuation marks alone in formatting tags often causes the engine to ignore them entirely.
Handling Line Breaks in JSON Payloads
When you type a message in the WhatsApp mobile app, you press the return key to start a new line. When you send a message through the WhatsApp Cloud API or an On-Premises API gateway, you must transmit that line break within a JSON payload.
In JSON, a line break is represented by the escape sequence \n. You cannot send a literal carriage return inside a JSON string without breaking the payload structure. Let us look at a raw JSON payload for a free-form session message:
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "923001234567",
"type": "text",
"text": {
"preview_url": false,
"body": "Order Confirmation\n\nHi *Sajid*,\nYour order *#9842* has been shipped.\n\nThank you!"
}
}
When Meta processes this payload, it converts each \n into a line break on the recipient's device. The customer will see "Order Confirmation" on the first line, followed by a blank line, and then the greeting on the third line.
The major technical trap here is double escaping. Depending on your backend programming language, your JSON encoder might automatically escape the backslash in your string. If your system sends \\n instead of \n, the WhatsApp application will display the literal characters "\n" in the chat window.
In PHP, using single quotes like '\n' treats the backslash as a literal character. You must use double quotes "\n" or let the json_encode() function handle the serialization of native line breaks. In Python, using json.dumps() with a native multi-line string or a string containing \n handles the escaping correctly. Always inspect the raw outgoing HTTP request payload to ensure it contains exactly one backslash before the 'n'.
The Template Parameter Trap
There is a massive difference between sending a session message (a free-form message sent within a 24-hour customer service window) and sending a template message (a pre-approved message used to initiate conversations).
If you want to use bold, italics, or line breaks in a template message, you must understand how Meta's template validation engine treats variables. You cannot pass markdown formatting characters inside a variable parameter to format the surrounding text.
For example, if you have a template approved as: "Your OTP is {{1}}."
If you send the parameter value as "*123456*", Meta will not render the OTP in bold. Instead, the user's phone will display: "Your OTP is *123456*." Meta does this to prevent developers from bypassing the template approval process by injecting unapproved text structures or links into variables.
To make a variable bold, you must build the formatting into the template itself during the submission phase in the Meta Business Suite. Your template text should be submitted and approved as: "Your OTP is *{{1}}*." Then, you simply pass the raw value "123456" in your API call, and the system renders it as bold.
Line breaks inside template variables behave differently. You can pass line breaks (\n) inside a template variable, provided the variable is placed within the body of the template. However, you cannot pass line breaks inside variables used in header fields or buttons. If you attempt to pass a line break in a header variable, the API will return an error or truncate the message.
Character Limits and Formatting Overhead
When designing formatted messages, you must keep track of character limits. Every formatting character you add counts against your payload limits.
| Message Component | Character Limit | Supports Formatting? | Supports Line Breaks? |
|---|---|---|---|
| Standard Text Body | 4096 characters | Yes (Bold, Italic, Strikethrough, Monospace) | Yes (\n) |
| Template Header (Text) | 60 characters | No (Bold is applied automatically to headers) | No |
| Template Footer | 60 characters | No | No |
| Quick Reply Button Text | 25 characters | No | No |
If you attempt to send a message body that exceeds 4096 characters, the API will reject the request with error code 100 (Invalid parameter). While 4096 characters is generous for standard communication, automated reports or long terms-and-conditions updates can easily hit this wall if you do not implement truncation checks in your code.
At WA Link, we build routing and management software for businesses using the WhatsApp Business API. While our platform helps you organize your messaging workflows, we do not have the power to change Meta's core API limitations. If you try to force a line break or bold markdown into a quick reply button through our system, Meta's API will reject the payload. You must work within the structural constraints of the official API.
Troubleshooting Common Formatting Failures
If your messages are not rendering correctly, check these common failure points:
The Trailing Space Bug: Ensure your code does not automatically append spaces to variable values. If your database returns " Karachi " with leading or trailing spaces, and your template is set to *{{1}}*, the rendered output becomes * Karachi *, which breaks the bold formatting.
HTML Tag Confusion: The WhatsApp API does not parse HTML. If you hook your WhatsApp API up to a CRM that uses a rich text editor, the CRM might output standard HTML tags like <strong> or <br>. WhatsApp will display these as raw text. You must write a helper function in your backend code to strip HTML and map those tags to WhatsApp's markdown equivalents before hitting the Meta API endpoint.
Malformed Nested Formatting: If you are nesting styles, make sure they do not overlap. Writing _*text*_ is valid. Writing _*text_*_ (with an extra trailing underscore) or *__text_* (unmatched pairs) will break the parsing engine. The system will fail silent, meaning it will not return an API error, but your customer will see raw formatting marks.
Frequently Asked Questions
Can I use bold and italics in list messages or interactive buttons?
No. Interactive elements like list section titles, row titles, row descriptions, and call-to-action buttons have strict plain-text requirements. If you include asterisks or underscores in these fields, they will display as literal characters. Row descriptions allow for standard text, but markdown styling is ignored.
Why do my line breaks work on Android but look different on iOS?
The rendering engine on Android and iOS can display spacing slightly differently, especially when consecutive line breaks (\n\n) are used. Android devices sometimes render compact spacing, while iOS devices may display wider gaps. Always test your message layouts on both operating systems before deploying them to production.
Do line breaks count as extra messages in my billing?
No. WhatsApp billing is conversation-based, not message-based. You are charged per 24-hour conversation window, regardless of how many messages or line breaks you send within that window. For more details on conversation-based pricing, you can refer to the Official Meta Developer Documentation.
Can I use emojis alongside bold formatting?
Yes. You can place emojis inside or outside formatting tags. For example, *🔥 Attention* will render the emoji and the word in bold. However, place the emoji outside the formatting characters if you notice rendering bugs on older device models.
Why does my API call fail when I use backslashes in my text?
If you are sending a raw backslash (\) in your message text, you must escape it in your JSON payload as \\. If you do not escape it, the JSON parser will assume the backslash is trying to escape the next character. If that next character is not a recognized escape sequence (like \n or \t), the payload will be invalid JSON, and the API will reject the request before it even reaches WhatsApp's delivery pipeline.
Your Next Step
Open your API development client or terminal, copy the raw JSON text payload shown in the line break section above, replace the destination phone number with your own test device number, and send a manual HTTP POST request to the Meta Cloud API endpoint to verify that your environment handles the single backslash character correctly without double-escaping it.