Install & Compatibility
Where this runs
tested against v3.25.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.598s · 55.8MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 8.0s · import 0.548s · 57MB
57MB installed
● package 57MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
LineBotApi
✓ from linebot import LineBotApi
WebhookHandler
✓ from linebot import WebhookHandler
MessageEvent
✓ from linebot.models import MessageEvent
TextMessage
✓ from linebot.models import TextMessage
TextSendMessage
✓ from linebot.models import TextSendMessage
InvalidSignatureError
✓ from linebot.exceptions import InvalidSignatureError
LineBotApi (old)
✓ from linebot import LineBotApi
✗ from linebot.api import LineBotApi
In v3.x, the LineBotApi class moved directly under the `linebot` namespace, removing the intermediate `.api` module found in v2.x.
This Flask example sets up a basic LINE webhook. It receives messages, verifies the signature, and replies with the user's message. Ensure `LINE_CHANNEL_SECRET` and `LINE_CHANNEL_ACCESS_TOKEN` environment variables are set. This snippet requires Flask to be installed (`pip install Flask`).
import os
from flask import Flask, request, abort
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage
)
app = Flask(__name__)
# Get channel_secret and channel_access_token from environment variable
channel_secret = os.environ.get('LINE_CHANNEL_SECRET', '')
channel_access_token = os.environ.get('LINE_CHANNEL_ACCESS_TOKEN', '')
if not channel_secret:
print('Specify LINE_CHANNEL_SECRET as environment variable.')
exit(1)
if not channel_access_token:
print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.')
exit(1)
line_bot_api = LineBotApi(channel_access_token)
handler = WebhookHandler(channel_secret)
@app.route("/callback", methods=['POST'])
def callback():
# get X-Line-Signature header value
signature = request.headers['X-Line-Signature']
# get request body as text
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
# handle webhook body
try:
handler.handle(body, signature)
except InvalidSignatureError:
print("Invalid signature. Please check your channel access token/channel secret.")
abort(400)
return 'OK'
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=f"You said: {event.message.text}")
)
if __name__ == "__main__":
app.run(port=8000)
Errors
Common errors & fixes
InvalidSignatureError: <InvalidSignatureError [Invalid signature. signature=...]>
The X-Line-Signature header in the incoming webhook request does not match the signature calculated by the SDK using your Channel Secret and the raw request body, often due to an incorrect Channel Secret, a modified request body by a proxy, or not providing the raw request body to the handler.
fixEnsure that the `WebhookHandler` is initialized with the correct `Channel Secret` and that you pass the exact raw request body (e.g., `request.get_data(as_text=True)` in Flask or `req.raw_body` in others) to `handler.handle(body, signature)` without any prior parsing that modifies it.
AttributeError: 'str' object has no attribute 'as_json_dict'
You are attempting to pass a plain string directly to message sending functions like `reply_message` or `push_message`, which expect a list of specific `Message` objects (e.g., `TextMessage`, `StickerMessage`).
fixWrap your message content in the appropriate `Message` object. For example, instead of `line_bot_api.reply_message(reply_token, 'Hello')`, use `from linebot.models import TextSendMessage` and then `line_bot_api.reply_message(reply_token, TextSendMessage(text='Hello'))` (for v2) or `from linebot.v3.messaging import TextMessage` and `line_bot_api.reply_message_with_http_info(ReplyMessageRequest(reply_token=event.reply_token, messages=[TextMessage(text='Hello')]))` (for v3).
ImportError: cannot import name 'TextMessage' from 'linebot.v3.messaging' (or similar for other v3 imports)
This error typically occurs when migrating from `line-bot-sdk` v2 to v3, as the import paths for many classes, including message types and API clients, have changed under the `linebot.v3` namespace.
fixUpdate your import statements to reflect the new `linebot.v3` module structure. For example, change `from linebot.models import TextMessage` to `from linebot.v3.messaging import TextMessage`, and `from linebot import LineBotApi` to `from linebot.v3.messaging import Configuration, ApiClient, MessagingApi`.
A timeout occurred when sending a webhook event object
The LINE platform did not receive an HTTP 2xx response from your bot's webhook endpoint within the stipulated time (typically 2 seconds), indicating that your server processing took too long or was unresponsive.
fixEnsure your webhook endpoint returns an immediate HTTP 200 OK response. Any heavy or time-consuming operations (like API calls to other services, database queries, or complex AI processing) should be offloaded to background tasks after sending the initial response.
Upgrade
Version history
3.25.0latest on PyPI · released Jul 7, 2026
Audit
Dependencies
flaskrequiredCommonly used for building webhook endpoints to receive LINE events.
pydanticrequiredUsed for data validation and parsing of API models.