Last updated: September 2026

Why is my LinkedIn API post cut off at a parenthesis or bracket?

Because LinkedIn reads the commentary field of a post as little text format, where parentheses, brackets and a handful of other characters are markup, not text. Left unescaped, one of them can cut the post off at that point. Put a backslash in front of every reserved character and the post publishes exactly as written.

Below is the full reserved set, an escape function in Python and JavaScript you can paste in, the one tradeoff escaping brings, and how OpenTweet handles it.

The reserved characters

Fifteen characters. Each one needs a backslash in front of it in commentary, including the backslash itself.

\|{}@[]()<>#*_~

Parentheses and brackets are the ones people notice, because they turn up in ordinary writing: a price in brackets, an aside in parentheses, a snake_case name. Every character above is markup to LinkedIn, so all of them get escaped, not only the ones that have caused trouble so far.

A copy-paste escape function

Escape the text once, right before it goes into the request body. Both versions below produce the same output.

escape.py
import re

RESERVED = re.compile(r"[\\|{}@\[\]()<>#*_~]")

def escape_little_text(text: str) -> str:
    return RESERVED.sub(lambda m: "\\" + m.group(0), text)


escape_little_text("Q3 results (up 40%) #growth")
# Q3 results \(up 40%\) \#growth
escape.js
const RESERVED = /[\\|{}@[\]()<>#*_~]/g;

function escapeLittleText(text) {
  return String(text ?? '').replace(RESERVED, (c) => '\\' + c);
}

escapeLittleText('Q3 results (up 40%) #growth');
// Q3 results \(up 40%\) \#growth

Here is one line of text on its way through. Note the JSON row: the escaping backslash is itself escaped by JSON, so it appears doubled on the wire.

Your text
Q3 results (up 40%) #growth
After escaping
Q3 results \(up 40%\) \#growth
In the JSON body
"commentary": "Q3 results \\(up 40%\\) \\#growth"
On LinkedIn
Q3 results (up 40%) #growth

Two ways to get this wrong

Writing the JSON by hand with a single backslash, as in \(, is not valid JSON, so let your JSON encoder add the second one. And escape exactly once: text escaped twice publishes with visible backslashes.

The tradeoff: hashtags and mentions become plain text

# and @ are in the reserved set, so escaping everything means a #hashtag or an @name publishes as the characters you typed, not as a clickable hashtag or mention.

The alternative is to leave some characters bare and hope the text never contains the wrong combination. For text you did not write character by character, such as AI drafts, imported posts or anything cross-posted from X, escaping everything is the safe choice: the post is never cut short, and the words all arrive.

OpenTweet escapes it for you

When you post to LinkedIn through OpenTweet, every reserved character is escaped before the text reaches LinkedIn, so parentheses and brackets publish as written. As above, hashtags and @mentions publish as plain text on LinkedIn. URLs in the text still work.

bash
curl -X POST https://opentweet.io/api/v1/posts \
  -H "Authorization: Bearer ot_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Q3 results (up 40%) [draft numbers] #growth",
    "platforms": ["linkedin"],
    "publish_now": true
  }'

Send the text as you wrote it, with no backslashes. The result comes back per network in results[], with the LinkedIn post URN as post_id. Add "x" or "bluesky" to the platforms array and the same text goes there unescaped, because those networks do not use this format.

LinkedIn posts through OpenTweet go to your personal profile, connected once in Settings > Accounts with no developer app. Text is limited to 3,000 characters counted in UTF-16 code units, so an emoji counts as 2. The escaping backslashes are not counted against you. Full limits are in the cross-posting docs.

7-day free trial. Cancel anytime.

Frequently asked questions

Why is my LinkedIn API post cut off at a parenthesis or bracket?

Because LinkedIn reads the commentary field as little text format, where parentheses, brackets and a dozen other characters are markup. An unescaped one can cut the post off at that point. Put a backslash before every reserved character and the post renders as written.

Which characters do I have to escape in LinkedIn commentary?

These 15: backslash, pipe, both curly braces, @, both square brackets, both parentheses, both angle brackets, #, asterisk, underscore and tilde. Escape the backslash along with the rest, so a literal backslash in your text survives.

Will the backslashes show up in the published post?

No. The backslash tells LinkedIn to treat the next character as text, and the post shows the character alone. Backslashes only show up if you escape the same text twice.

Does escaping break hashtags and mentions?

It turns them into plain text. An escaped #tag or @name publishes as the characters you typed, not as a link. That is the tradeoff for text that never gets cut off.

Do I have to escape anything when posting to LinkedIn through OpenTweet?

No. OpenTweet escapes every reserved character before the text reaches LinkedIn, so parentheses and brackets publish as written. Hashtags and @mentions publish as plain text for the same reason.

Send the text as written. It arrives whole.

OpenTweet escapes LinkedIn text for you, from one API call. LinkedIn is on every plan from $11.99 a month.

7-day free trial. Cancel anytime.