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.
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%\) \#growthconst RESERVED = /[\\|{}@[\]()<>#*_~]/g;
function escapeLittleText(text) {
return String(text ?? '').replace(RESERVED, (c) => '\\' + c);
}
escapeLittleText('Q3 results (up 40%) #growth');
// Q3 results \(up 40%\) \#growthHere 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.
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.
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.
Keep exploring
The other LinkedIn API surprises, and how to post without any of them.
LinkedIn API 426 NONEXISTENT_VERSION
The LinkedIn-Version header names a retired or unreleased version. How to pick one that works.
The LinkedIn API without a Company Page
Posting to your profile needs no Page. Registering the app does.
Do I need partner approval?
Not for your own profile. Company Pages are where LinkedIn review sits.
How to cross-post to LinkedIn
Send one draft to X, Bluesky and LinkedIn, step by step.
Cross-posting API reference
The platforms parameter, the results array, and the per-network limits.
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.