Skip to content

copyMessage

Use this method to copy messages of any kind. Service messages, paid media messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. A quiz poll can be copied only if the value of the field correct_option_id is known to the bot. The method is analogous to the method forwardMessage, but the copied message doesn't have a link to the original message. Returns the MessageId of the sent message on success.

Parameters

chat_idIntegerStringRequired
Unique identifier for the target chat or username of the target channel (in the format @channelusername)
message_thread_idIntegerOptional
Unique identifier for the target message thread (topic) of a forum; for forum supergroups and private chats of bots with forum topic mode enabled only
direct_messages_topic_idIntegerOptional
Identifier of the direct messages topic to which the message will be sent; required if the message is sent to a direct messages chat
from_chat_idIntegerStringRequired
Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername)
message_idIntegerRequired
Message identifier in the chat specified in from\chat\id
video_start_timestampIntegerOptional
New start timestamp for the copied video in the message
captionStringOptional✏️ FormattableminLen 0maxLen 1024
New caption for media, 0-1024 characters after entities parsing. If not specified, the original caption is kept
parse_modeStringOptional
Mode for parsing entities in the new caption. See formatting options for more details.
caption_entitiesMessageEntity[]Optional
A JSON-serialized list of special entities that appear in the new caption, which can be specified instead of parse\_mode
show_caption_above_mediaBooleanOptional
Pass True, if the caption must be shown above the message media. Ignored if a new caption isn't specified.
disable_notificationBooleanOptional
Sends the message silently. Users will receive a notification with no sound.
protect_contentBooleanOptional
Protects the contents of the sent message from forwarding and saving
allow_paid_broadcastBooleanOptional
Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance
message_effect_idStringOptional
Unique identifier of the message effect to be added to the message; only available when copying to private chats
suggested_post_parametersSuggestedPostParametersOptional
A JSON-serialized object containing the parameters of the suggested post to send; for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post is automatically declined.
reply_parametersReplyParametersOptional
Description of the message to reply to
Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user

Returns

On success, the MessageId object is returned.

GramIO Usage

ts
// Copy a message from one chat to another (no forwarding attribution)
const 
result
= await
bot
.
api
.
copyMessage
({
chat_id
: -1001234567890,
from_chat_id
: "@sourcechannel",
message_id
: 42,
});
console
.
log
("Copied message ID:",
result
.
message_id
);
ts
// Copy a message from context (e.g., relay a user message to an admin group)
bot
.
on
("message", async (
ctx
) => {
await
bot
.
api
.
copyMessage
({
chat_id
: -1009876543210, // admin group
from_chat_id
:
ctx
.
chatId
,
message_id
:
ctx
.
id
,
}); });
ts
// Copy a media message and replace its caption using GramIO format helpers
await 
bot
.
api
.
copyMessage
({
chat_id
: -1001234567890,
from_chat_id
: "@sourcechannel",
message_id
: 100,
caption
:
format
`${
bold
("New Title")} — ${
italic
("Updated caption")}`,
});
ts
// Copy a message and attach an inline keyboard
await 
bot
.
api
.
copyMessage
({
chat_id
: -1001234567890,
from_chat_id
: "@sourcechannel",
message_id
: 55,
reply_markup
: new
InlineKeyboard
().
text
("Open original", "open_55"),
});
ts
// Silent copy (no notification sound) with content protection
await 
bot
.
api
.
copyMessage
({
chat_id
: -1001234567890,
from_chat_id
: -1009876543210,
message_id
: 77,
disable_notification
: true,
protect_content
: true,
});

Errors

CodeErrorCause
400Bad Request: chat not foundchat_id or from_chat_id is invalid or the bot has no access
400Bad Request: message not foundmessage_id does not exist in from_chat_id
400Bad Request: can't copy this type of messageAttempted to copy a service message, invoice, paid media, giveaway, or giveaway winners message
400Bad Request: message is protectedThe source message has protect_content enabled and cannot be copied
400Bad Request: wrong quiz correct_option_idQuiz poll copied without correct correct_option_id being known to the bot
400Bad Request: caption too longcaption exceeds 1024 characters
403Forbidden: bot is not a member of the channel chatBot is not in the target channel
429Too Many Requests: retry after NRate limit hit — check retry_after, use auto-retry plugin

TIP

Use GramIO's auto-retry plugin to handle 429 errors automatically when broadcasting messages to many users.

Tips & Gotchas

  • No forwarding attribution. Unlike forwardMessage, the copied message shows no "Forwarded from" header. Use this when you want to relay content without revealing the source.
  • Caption override is optional. If you omit caption, the original caption is preserved. Pass an empty string "" to remove the caption entirely.
  • parse_mode and caption_entities are mutually exclusive. GramIO's format helper always produces caption_entities, so never pass parse_mode alongside it.
  • Service messages cannot be copied. This includes join/leave notifications, pinned message notices, invoice messages, and others. Copy only regular text/media messages.
  • Quiz polls need correct_option_id. A bot can only copy a quiz poll if it knows the correct option. If the bot never saw the answer, it cannot copy a quiz.
  • protect_content on source blocks copying. If the original message has content protection, copyMessage will fail with a 400 error.
  • For bulk copying, use copyMessages. It supports 1–100 message IDs in a single call and preserves media album grouping.

See Also