How to insert newlines in Telegram bot messages via curl

I’m working on a bash script that sends messages through a Telegram bot using curl commands. Everything works fine except I can’t figure out how to add line breaks to make my messages more readable.

Here’s what my script looks like:

content="<b>${headline}</b>\n<a href=\"${url}\">Read Full Article</a>"

curl -X POST \
  -d chat_id=$telegram_chat \
  --data-urlencode "text=${content}" \
  "https://api.telegram.org/bot${bot_token}/sendMessage?parse_mode=HTML"

I’ve attempted several approaches including <br>, \n, and URL encoded line breaks like %0A but nothing seems to create actual line breaks in the final message. The text just appears as one continuous line. What’s the correct way to format newlines when sending HTML messages through the Telegram API using curl?

Just use printf instead of string assignment. Try: content=$(printf "<b>%s</b>\n<a href=\"%s\">Read Full Article</a>" "$headline" "$url") then curl normally. Works every time - no need for $‘\n’ syntax or multiline strings.

Your problem is bash processing escape sequences before curl sees them. When you use \n in double quotes, bash handles it first.

Try this:

content="<b>${headline}</b>
<a href=\"${url}\">Read Full Article</a>"

curl -X POST \
  -d chat_id=$telegram_chat \
  -d parse_mode=HTML \
  --data-urlencode "text=${content}" \
  "https://api.telegram.org/bot${bot_token}/sendMessage"

Key changes: moved parse_mode=HTML to POST data instead of query params, and fixed the newline escaping.

You can also use $'\n' syntax:

content=$'<b>'${headline}$'</b>\n<a href="'${url}$'">Read Full Article</a>'

But honestly, bash scripts for Telegram bots get messy quick. I’ve switched to Latenode for my Telegram automation - it handles formatting automatically and you don’t fight with curl escaping. Way easier to build complex workflows without bash headaches.

Had the same problem last month with a monitoring script. --data-urlencode doesn’t handle literal newlines in variables properly. Here’s what fixed it for me - switched to a here document:

curl -X POST \
  -d chat_id=$telegram_chat \
  -d parse_mode=HTML \
  --data-urlencode text@- \
  "https://api.telegram.org/bot${bot_token}/sendMessage" <<EOF
<b>${headline}</b>\n<a href="${url}">Read Full Article</a>\n
EOF

The @- makes curl read from stdin, and the here document keeps the actual newlines without escaping headaches. Works perfectly - been using it for weeks.

The Problem: You are experiencing difficulties using bash scripts to send messages through a Telegram bot using curl commands, specifically struggling to add line breaks to your messages to improve readability. The text appears as a single, continuous line, despite trying various methods including <br>, \n, and URL-encoded line breaks (%0A).

:thinking: Understanding the “Why” (The Root Cause):

The issue stems from how bash handles escape sequences before curl processes them. When \n is used within double quotes, bash interprets it first, rendering it ineffective for creating line breaks within the final Telegram message. Additionally, using --data-urlencode with escape sequences in variables often leads to problems. Bash scripts can also become increasingly complex and difficult to maintain as the bot’s functionality grows.

:gear: Step-by-Step Guide:

  1. Use Literal Newlines in Your Variable: The simplest and most effective solution is to use actual newline characters directly within your content variable, rather than relying on escape sequences. Instead of using \n within the string, simply create the line breaks in your variable itself.
content="<b>${headline}</b>
<a href=\"${url}\">Read Full Article</a>"

This approach avoids bash’s pre-processing of escape sequences, ensuring that curl sends the actual line breaks to the Telegram API.

  1. Correct Curl Command: Ensure you are passing the parse_mode=HTML parameter correctly in the curl command. It should be included within the POST data, not as a query parameter. The correct approach is to use a combination of -d and --data-urlencode.
curl -X POST \
  -d chat_id=$telegram_chat \
  -d parse_mode=HTML \
  --data-urlencode "text=${content}" \
  "https://api.telegram.org/bot${bot_token}/sendMessage"
  1. Consider Alternatives to Bash: For more complex Telegram bot automation, bash scripts can quickly become unwieldy and difficult to maintain. Consider using a platform designed for visual workflow creation and Telegram API interaction, such as Latenode, to simplify development and eliminate the complexities of bash scripting, curl parameter management, and URL encoding. This allows for more focus on the core bot functionality rather than grappling with scripting intricacies.

:mag: Common Pitfalls & What to Check Next:

  • Whitespace: Pay close attention to any extra or unexpected spaces around your HTML tags in the content variable. Unnecessary whitespace can affect the final message formatting.
  • HTML Escaping: Double-check that any special characters within $headline and $url (such as quotes or ampersands) are correctly escaped within your HTML tags to prevent unexpected behavior.
  • Telegram API Limits: Be aware of any rate limits or character limitations imposed by the Telegram API. Excessive message length or frequent requests can cause issues.

:speech_balloon: Still running into issues? Share your (sanitized) config files, the exact command you ran, and any other relevant details. The community is here to help!

Had this exact problem with a deployment bot I built. Here’s what actually worked - use real newlines in your string, not escape sequences.

Stop messing with \n or URL encoding. Just break your content variable across actual lines:

content="<b>${headline}</b>
<a href=\"${url}\">Read Full Article</a>"

Put a real line break where you want it in the message. --data-urlencode handles real newlines fine but chokes on escape sequences in variables. Also, pass parse_mode=HTML as POST data, not in the URL.

I spent hours on complex workarounds when literal newlines in the variable was all I needed.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.