{"id":40,"library":"line","title":"LINE Messaging API","description":"LINE Messaging API enables bot development for LINE, the dominant messaging platform in Japan, Thailand, and Taiwan with 196M+ monthly users. Official SDKs exist for Python and Node.js. Primary documentation is in Japanese — English docs are complete but may lag Japanese versions.","status":"active","version":"3.21.0","language":"python","source_language":"ja","source_url":"https://developers.line.biz/en/docs/messaging-api/line-bot-sdk/","tags":["line","messaging","bot","webhook","japan","thailand","taiwan","python","nodejs"],"install":[{"cmd":"pip install line-bot-sdk","lang":"bash","label":"Python"},{"cmd":"npm install @line/bot-sdk","lang":"bash","label":"Node.js"}],"dependencies":[{"reason":"Required for webhook server in Python examples. Any WSGI framework works.","package":"flask","optional":true}],"imports":[{"note":"linebot v2 imports (no .v3) still work but are legacy. All new code should use linebot.v3 namespace.","wrong":"from linebot import WebhookHandler","symbol":"WebhookHandler (Python v3)","correct":"from linebot.v3 import WebhookHandler"},{"note":"LineBotApi is the v2 class. Replaced by MessagingApi in v3. Both still work but v3 is current.","wrong":"from linebot import LineBotApi","symbol":"MessagingApi (Python v3)","correct":"from linebot.v3.messaging import Configuration, ApiClient, MessagingApi"}],"quickstart":{"code":"from flask import Flask, request, abort\nfrom linebot.v3 import WebhookHandler\nfrom linebot.v3.exceptions import InvalidSignatureError\nfrom linebot.v3.messaging import (\n    Configuration, ApiClient, MessagingApi,\n    ReplyMessageRequest, TextMessage\n)\nfrom linebot.v3.webhooks import MessageEvent, TextMessageContent\n\napp = Flask(__name__)\nconfiguration = Configuration(access_token='YOUR_CHANNEL_ACCESS_TOKEN')\nhandler = WebhookHandler('YOUR_CHANNEL_SECRET')\n\n@app.route('/callback', methods=['POST'])\ndef callback():\n    signature = request.headers['X-Line-Signature']\n    body = request.get_data(as_text=True)\n    try:\n        handler.handle(body, signature)\n    except InvalidSignatureError:\n        abort(400)\n    return 'OK'\n\n@handler.add(MessageEvent, message=TextMessageContent)\ndef handle_message(event):\n    with ApiClient(configuration) as api_client:\n        line_bot_api = MessagingApi(api_client)\n        line_bot_api.reply_message(\n            ReplyMessageRequest(\n                reply_token=event.reply_token,\n                messages=[TextMessage(text=event.message.text)]\n            )\n        )\n\nif __name__ == '__main__':\n    app.run()","lang":"python","description":"Minimal LINE bot webhook handler using linebot.v3 SDK with Flask."},"warnings":[{"fix":"Always call handler.handle(body, signature) and catch InvalidSignatureError. Abort 400 on failure.","message":"Signature verification is mandatory. Never process webhook events without verifying X-Line-Signature header using HMAC-SHA256 with your channel secret.","severity":"breaking","affected_versions":"all"},{"fix":"Register LINE middleware before any body parser middleware on the webhook route","message":"Do not use body parsers (bodyParser.json, express.json) before LINE webhook middleware in Node.js. Pre-parsing the body breaks signature verification.","severity":"breaking","affected_versions":"all"},{"fix":"Use push messages (push_message API) for delayed or async responses instead of reply tokens","message":"Reply tokens are single-use and expire in 30 seconds. Storing and reusing a reply token will fail silently.","severity":"breaking","affected_versions":"all"},{"fix":"Process webhook events asynchronously. Return 200 immediately, handle events in background.","message":"Webhook endpoint must return HTTP 200 within 30 seconds. LINE Platform retries failed webhooks if webhook redelivery is enabled.","severity":"gotcha","affected_versions":"all"},{"fix":"Channel secret → WebhookHandler constructor. Channel access token → Configuration/MessagingApi.","message":"Channel access token and channel secret are different credentials. Confusing them is the most common setup error.","severity":"gotcha","affected_versions":"all"},{"fix":"Track opt-out webhook events to maintain your own block list and avoid unnecessary push API calls.","message":"No error is returned when pushing messages to users who have blocked the bot. Delivery silently fails.","severity":"gotcha","affected_versions":"all"},{"fix":"Use https://api-data.line.me/v2/bot/message/{messageId}/content for binary content retrieval","message":"Content from user messages (images, video, audio) must be fetched separately via GET /v2/bot/message/{messageId}/content using api-data.line.me domain, not api.line.me.","severity":"gotcha","affected_versions":"all"},{"fix":"Ensure all necessary Python packages are installed in the environment where the script is executed. This can be done using `pip install <package_name>` for individual packages or `pip install -r requirements.txt` if a `requirements.txt` file is used to list dependencies.","message":"Missing required Python packages (e.g., Flask, Django, etc.) will cause a `ModuleNotFoundError` when the application attempts to import them. This prevents the application from starting or functioning correctly.","severity":"breaking","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-05-12T05:24:54.758Z","next_check":"2026-05-28T00:00:00.000Z","problems":[{"fix":"Ensure the 'Channel Secret' in your bot application exactly matches the one in the LINE Developers Console, and use the raw request body without any modification (e.g., pretty-printing JSON) for signature validation with UTF-8 encoding.","cause":"The webhook signature sent by the LINE Platform does not match the signature calculated by your bot server, often due to an incorrect Channel Secret or modifications to the request body before verification.","error":"InvalidSignatureError: <InvalidSignatureError [Invalid signature. signature=...]>"},{"fix":"Verify that the 'Channel Access Token' in your code is correct and currently valid in the LINE Developers Console. If it's a short-lived token, ensure it hasn't expired, and if it's been reissued or revoked, obtain a new valid token.","cause":"The Channel Access Token used for API requests is invalid, expired, revoked, or incorrectly configured.","error":"LineBotApiError [Authentication failed due to the following reason: invalid token. Confirm that the access token in the authorization...]"},{"fix":"Ensure the 'reply_token' is used immediately after receiving the event and has not been used before, as reply tokens are single-use and time-sensitive. Also, verify that the message objects in your request adhere to the LINE Messaging API specifications.","cause":"This error, often accompanied by an 'invalid replyToken', indicates an issue with the request payload sent to the LINE Messaging API, such as using an expired, already used, or incorrectly formatted reply token or message object.","error":"Request failed with status code 400"},{"fix":"Install the library using pip: `pip install line-bot-sdk`. Confirm that your script is being executed within the Python environment where the package was installed.","cause":"The 'line-bot-sdk' Python package has not been installed or is not accessible in the current Python environment.","error":"ModuleNotFoundError: No module named 'linebot'"},{"fix":"Update your imports and code to use the `linebot.v3` modules and classes as specified in the deprecation warning, adapting your code to the new API structure.","cause":"Your code is using older modules or methods from the `linebot` (version 2.x) namespace, but a newer version of the SDK (3.x) is installed, which has introduced a `v3` namespace with breaking changes.","error":"LineBotSdkDeprecatedIn30: Call to deprecated method ... (Use 'from linebot.v3.messaging import MessagingApi' and 'MessagingApi(...)....' instead. See https://github.com/line/line-bot-sdk-python/blob/master/README.rst for more details.) -- Deprecated since version 3.0.0."}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.6,"mem_mb":29,"disk_size":"117.1M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.17,"mem_mb":29,"disk_size":"189M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.08,"mem_mb":31.3,"disk_size":"129.4M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.73,"mem_mb":31.3,"disk_size":"201M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.13,"mem_mb":30.8,"disk_size":"119.5M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.11,"mem_mb":30.8,"disk_size":"191M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.05,"mem_mb":31.9,"disk_size":"116.0M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.04,"mem_mb":31.9,"disk_size":"190M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.47,"mem_mb":27.2,"disk_size":"116.9M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.34,"mem_mb":27.2,"disk_size":"190M"}]},"quickstart_checks":{"last_tested":"2026-05-12","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}