The short answer: seven steps from zero to a replying bot
To make a LINE bot, create a LINE Official Account, enable the Messaging API for it in LINE Official Account Manager (which creates the Messaging API channel), issue a channel access token, and point the channel's webhook URL at an HTTPS server that verifies the x-line-signature header and returns 200. Your server then answers each message event with the reply endpoint, using the event's reply token.
Last verified: November 2026 against LINE's Get started with the Messaging API guide, the Build a bot guide and the Messaging API reference.
- Create a LINE Official Account. Register a Business ID and fill in the entry form. The account appears in LINE Official Account Manager.
- Enable the Messaging API for that account in Official Account Manager and pick a provider. This creates the Messaging API channel. You can no longer create one directly in the LINE Developers Console.
- Issue a channel access token in the LINE Developers Console. A long-lived token is the fastest start; LINE recommends channel access token v2.1 for production.
- Copy the channel secret from the Basic settings tab. It is the key for verifying webhook signatures.
- Deploy a webhook endpoint on HTTPS with a certificate from a widely trusted authority. It must verify the signature against the raw body and return 200 quickly.
- Set the webhook URL on the Messaging API tab, press Verify, and turn on Use webhook. Then switch off the account's default auto-reply and greeting messages so they don't answer for your bot.
- Add the account as a friend (scan the QR code on the Messaging API tab), send it a message, and reply with
POST /v2/bot/message/reply.
The rest of this guide covers each step with working code, the token type to choose, the free-message quota that catches people out, and the mistakes that make a new bot silent. If you already built one and it doesn't answer, go straight to LINE bot not responding, which is ordered by how often each cause happens.
The moving parts: Official Account, provider, channel and two consoles
LINE's setup confuses first-timers because a single bot is spread across four objects and two web consoles. Knowing which is which saves most of the clicking around.
| Piece | What it is | Where you manage it |
|---|---|---|
| LINE Official Account | The account users add as a friend and chat with. Its name, profile and rich menu are what users see. | LINE Official Account Manager (manager.line.biz) |
| Provider | The company or person that owns channels. User IDs are issued per provider, so the same person has a different user ID under two providers. | LINE Developers Console |
| Messaging API channel | The API side of the Official Account: channel secret, access tokens, webhook URL and API settings. | LINE Developers Console (developers.line.biz/console) |
| Your bot server | The HTTPS endpoint that receives webhook events and calls the Messaging API. | Your own hosting |
The two consoles overlap. Greeting messages, auto-reply messages and the business profile live in Official Account Manager. Tokens, the webhook URL, signature secrets and group-chat permission live in the Developers Console. LINE's own build guide links between them, and the Developers Console's Edit buttons for greeting and auto-reply simply open Official Account Manager.
One decision here is permanent. LINE's getting-started guide warns that once you assign a provider to manage the Official Account, you can't change or de-assign it, and channels can't be moved between providers later. If an agency or tool vendor owns the provider, the user IDs your bot collects belong to that provider's namespace. Create the provider under your own company before you enable the Messaging API.
Step 1: Create the LINE Official Account
Everything starts with an Official Account, because since September 4, 2024 LINE no longer lets you create Messaging API channels directly from the Developers Console. LINE announced the change in its developer news, and older tutorials that start with "Create a new channel" in the console no longer work.
- Go to the Business ID sign-up. You can register with a LINE account or an email address.
- Fill in the entry form that appears next: account name, business category, region and contact details. Submitting it creates the Official Account.
- Open LINE Official Account Manager and confirm the account is listed.
The region you pick matters later, because pricing and free-message quotas are set per country or region. More on that in the quota section below.
Use a work identity you can hand over, not a personal LINE account, and add a second admin on the account and on the provider once they exist, so that one person leaving doesn't lock you out of your own bot.
Step 2: Enable the Messaging API and choose a provider
In Official Account Manager, open the account's settings, find the Messaging API section and enable it. LINE then asks for two things:
- Developer information. If your login has never been used in the Developers Console, you enter a name and email to create a developer account.
- A provider. Pick an existing provider (you need the Admin role on it to see it) or create a new one. If you plan to add LINE Login or a LINE MINI App later and want user IDs to match across them, choose the same provider those channels will use.
That creates the Messaging API channel. Log in to the LINE Developers Console with the same account, open the provider, and the channel is there. Two tabs matter for the rest of this guide:
| Tab | What you take from it |
|---|---|
| Basic settings | Channel ID, channel secret, assertion signing keys for token v2.1 |
| Messaging API | QR code for adding the bot, channel access token (long-lived), webhook URL, Use webhook, Allow bot to join group chats, webhook redelivery, error statistics |
The channel secret is a shared HMAC key. LINE's signature guide calls it a private key known only to the LINE Platform and the developer, and you need Admin privileges on the channel to view or reissue it. Reissuing it invalidates the old one at once, so a colleague who presses Issue breaks every running server that still holds the old value.
Step 3: Issue a channel access token (and pick the right type)
Every Messaging API call carries Authorization: Bearer {channel access token}. LINE offers four token types, and they differ in lifetime and in how many can exist at once. This table is from LINE's channel access token page:
| Type | Validity | Issued per channel | How you get it |
|---|---|---|---|
| Long-lived | Indefinite | 1 | Issue button on the Messaging API tab |
| Channel access token v2.1 (user-specified expiration) | Up to 30 days | 30 | Sign a JWT with your own key, then call POST /oauth2/v2.1/token |
| Short-lived | 30 days | 30 (the oldest is revoked when you exceed it) | API call with channel ID and secret |
| Stateless | 15 minutes | No limit; can't be revoked | POST /oauth2/v3/token with channel ID and secret, or a JWT |
Which one to use
- Getting started or a single small bot: the long-lived token. One click, never expires. Reissuing it invalidates the current one, and LINE lets you keep the old one alive for up to 24 hours while you roll the new one out. It is also the only type you can lock to your server's IP addresses, on the channel's Security tab.
- Production, per LINE's recommendation: channel access token v2.1. You generate an RS256 key pair, register the public key on the Basic settings tab to get a
kid, then sign a short JWT whenever you need a new token. The private key never leaves your server. - Serverless and short jobs: stateless tokens, issued fresh for each run. Nothing to store, but nothing to revoke either.
Issuing a v2.1 token
The JWT header is {"alg":"RS256","typ":"JWT","kid":"..."}. The payload uses your channel ID for both iss and sub, https://api.line.me/ as aud, an exp no more than 30 minutes ahead, and token_exp in seconds, up to 30 days. Exchange it like this:
curl -X POST https://api.line.me/oauth2/v2.1/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
--data-urlencode 'client_assertion={JWT}'The response pairs the token with a key_id. LINE's v2.1 guide asks you to store the pair, since the key ID is how you revoke or audit a specific token later. Don't issue a new v2.1 token on every request: tokens are reusable within their validity, and LINE may temporarily restrict issuance if you hammer the endpoint. Refresh on a schedule before expiry instead.
Treat the token like a password
Anyone holding it can send a broadcast to every friend of your account, which LINE itself gives as the example of why a leaked token is dangerous. Keep it in a secret store, out of client-side code and out of logs. If one leaks, revoke it from the console or the revoke endpoint for its type. A stale or wrong token shows up as 401 Authentication failed; an expired v2.1 or short-lived token as The access token expired; and too many live v2.1 tokens as maximum number of access tokens issued.
Step 4: Build the webhook server (Node.js and Python)
LINE delivers every event, such as a message, a follow, a postback or a group join, as an HTTPS POST to one webhook URL per channel. Your endpoint has four jobs, all spelled out in the webhook reference:
- Verify
x-line-signatureagainst the raw request body using HMAC-SHA256 with the channel secret, Base64-encoded. Header names are case-insensitive, and LINE warns the casing may change, so never look the header up case-sensitively. - Return 200 fast. LINE's error statistics record a
request_timeoutwhen your server doesn't answer within 2 seconds. Acknowledge first, then do the work asynchronously, which is also LINE's stated recommendation. - Accept an empty
eventsarray. The console's Verify button and LINE's own connectivity checks send{"destination":"U...","events":[]}, which must get a 200. - Tolerate duplicates and new fields. The same event can arrive more than once; use
webhookEventIdto dedupe. LINE also adds properties and event types without notice, so ignore what you don't recognize instead of failing.
Node.js (Express, Node 18 or later)
const crypto = require("crypto");
const express = require("express");
const CHANNEL_SECRET = process.env.LINE_CHANNEL_SECRET;
const ACCESS_TOKEN = process.env.LINE_CHANNEL_ACCESS_TOKEN;
const app = express();
function isValidSignature(rawBody, signature) {
const expected = crypto.createHmac("sha256", CHANNEL_SECRET).update(rawBody).digest();
const received = Buffer.from(signature || "", "base64");
return received.length === expected.length && crypto.timingSafeEqual(received, expected);
}
async function reply(replyToken, messages) {
const res = await fetch("https://api.line.me/v2/bot/message/reply", {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: `Bearer ${ACCESS_TOKEN}` },
body: JSON.stringify({ replyToken, messages }),
});
if (!res.ok) console.error("reply failed", res.status, res.headers.get("x-line-request-id"), await res.text());
}
// express.raw keeps the exact bytes LINE signed; express.json() here would break verification.
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
if (!isValidSignature(req.body, req.get("x-line-signature"))) return res.sendStatus(401);
res.sendStatus(200); // answer inside LINE's 2-second window, then do the work
const { events = [] } = JSON.parse(req.body.toString("utf8"));
for (const event of events) {
if (event.type === "message" && event.message.type === "text" && event.replyToken) {
reply(event.replyToken, [{ type: "text", text: `You said: ${event.message.text}` }]).catch(console.error);
}
}
});
app.listen(process.env.PORT || 3000);Python (Flask)
import base64, hashlib, hmac, json, os, threading
import requests
from flask import Flask, abort, request
CHANNEL_SECRET = os.environ["LINE_CHANNEL_SECRET"]
ACCESS_TOKEN = os.environ["LINE_CHANNEL_ACCESS_TOKEN"]
app = Flask(__name__)
def is_valid_signature(raw_body: bytes, signature: str) -> bool:
digest = hmac.new(CHANNEL_SECRET.encode("utf-8"), raw_body, hashlib.sha256).digest()
return hmac.compare_digest(base64.b64encode(digest).decode("ascii"), signature or "")
def handle(events):
for event in events:
if event.get("type") == "message" and event["message"].get("type") == "text" and event.get("replyToken"):
r = requests.post(
"https://api.line.me/v2/bot/message/reply",
headers={"Authorization": f"Bearer {ACCESS_TOKEN}"},
json={"replyToken": event["replyToken"],
"messages": [{"type": "text", "text": "You said: " + event["message"]["text"]}]},
timeout=10,
)
if not r.ok:
print("reply failed", r.status_code, r.headers.get("x-line-request-id"), r.text)
@app.post("/webhook")
def webhook():
raw = request.get_data() # the exact bytes LINE signed
if not is_valid_signature(raw, request.headers.get("x-line-signature")):
abort(401)
events = json.loads(raw.decode("utf-8")).get("events", [])
threading.Thread(target=handle, args=(events,), daemon=True).start()
return "OK", 200We ran both against LINE's published test vector: the body {"destination":"U8e742f61d673b39c7fff3cecb7536ef0","events":[]} with channel secret 8c570fa6dd201bb328f1c1eac23a96d8 must produce GhRKmvmHys4Pi8DxkF4+EayaH0OqtJtaZxgTD9fMDLs=. Both accept it, both reject a wrong signature with 401, and both reply to a signed message event. You can check your own implementation the same way with the openssl one-liner in LINE's signature guide. A background thread is fine for a tutorial; in production, put events on a queue so a restart doesn't drop them.
Why signatures fail on valid requests
Almost always, something changed the body before you hashed it: a JSON body parser that re-serialized it, pretty-printing, a proxy that rewrote it, or a non-UTF-8 decode that turned \n into \r\n. The other causes on LINE's list are using HMAC-SHA1 instead of SHA-256, the secret of a different channel, and a secret a colleague just reissued. Note that LINE doesn't publish webhook source IPs and its development guidelines tell you not to filter by IP. The signature is the only authenticity check, so never skip it. Meta's webhooks use the same HMAC idea with a different header, covered in Meta webhook verification failed.
The official SDKs
If you'd rather not hand-roll this, LINE maintains official SDKs for Java, PHP, Python, Node.js, Go and Ruby; the Perl SDK is archived. As of this check the Node.js package @line/bot-sdk is at 11.4.0 and the Python line-bot-sdk at 3.27.0, which needs Python 3.10 or later. Both include signature-checking middleware. The same rule applies there: mount the SDK's middleware before any global JSON parser, or it verifies a re-serialized body and fails.
Step 5: Connect the webhook and fix the console settings
With the server deployed, finish the channel configuration on the Messaging API tab:
- Under Webhook URL, click Edit, enter your HTTPS endpoint and click Update. Self-signed certificates are rejected, and an incomplete certificate chain is a common cause of failures. Only one URL can be set per channel.
- Click Verify. Success means LINE reached your server and got a 200 for the empty-events request. A failure here maps to the delivery errors in our directory: could not connect, request timed out or an error status code. A URL LINE won't even accept shows up as Invalid webhook endpoint URL.
- Turn on Use webhook. Verify can succeed with this off, and then no real events are delivered. It is the single most common reason a correct bot stays silent.
- In Official Account Manager, set Greeting messages and Auto-reply messages to Disabled. Both default to Enabled on a new channel, and LINE's build guide recommends turning them off on your first bot so you can tell your bot's replies from the account's canned ones.
- Optional: enable Allow bot to join group chats (off by default) if the bot should work in groups. Only one Official Account can be in a given group at a time.
- Optional but recommended: enable Webhook redelivery and Error statistics aggregation. Redelivery resends events your server failed to accept, keeping the same
webhookEventIdand reply token. Error statistics show each failed delivery with a reason, timed in UTC+9, and can be downloaded as TSV.
Then scan the QR code on the Messaging API tab to add the account as a friend and send it a message. A quick way to confirm events arrive at all, from LINE's own guide: block the account in the LINE app and look for an unfollow event in your logs, then unblock it. If your server logs nothing, read our general webhook not firing guide before touching the code.
Step 6: Send messages, reply vs push
LINE has two ways to send, and the difference decides both your code and your bill.
| Reply message | Push, multicast, narrowcast, broadcast | |
|---|---|---|
| Endpoint | POST /v2/bot/message/reply | /v2/bot/message/push, /multicast, /narrowcast, /broadcast |
| When | Only in response to an event that carries a reply token | Any time, to users who are friends of the account |
| Counts toward the monthly message quota | No | Yes, one per recipient |
| Message objects per request | Up to 5 | Up to 5 (multicast: up to 500 user IDs per call) |
| Retry safety | A reply token is single-use | Send an X-Line-Retry-Key UUID so a retry can't deliver twice |
The reply token rules
The reply reference is precise, and it is shorter than many tutorials claim:
- A reply token can be used once.
- It must be used within one minute of receiving the webhook. Use after that isn't guaranteed to work, and LINE says the limit can change without notice, so reply as soon as possible rather than coding to the deadline.
- A redelivered webhook carries the same token, usable within a minute of the redelivery, but not if the original was already used or more than 20 minutes have passed since the event.
- An edited message arrives as a
messageEditedevent with its own, different reply token.
Miss the window or reuse a token and you get Invalid reply token. If the answer takes time, as an AI-generated one can, two tools help. First, call POST /v2/bot/chat/loading/start with a loadingSeconds value in steps of 5, from 5 to 60 (default 20), to show a typing animation in a one-to-one chat (not groups). Second, if you still miss the window, fall back to a push, which works but counts toward your quota.
Push safely
curl -X POST https://api.line.me/v2/bot/message/push \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {channel access token}' \
-H 'X-Line-Retry-Key: 123e4567-e89b-12d3-a456-426614174000' \
-d '{"to":"U4af4980629...","messages":[{"type":"text","text":"Your order has shipped."}]}'If the first attempt times out and you retry with the same key, LINE answers 409 retry key already accepted instead of sending a duplicate, and includes the original request ID in X-Line-Accepted-Request-Id. Pushing to someone who blocked the account isn't delivered or counted, and profile lookups for them return 404 Not found. Text messages are limited to 5,000 characters, counted in UTF-16 code units, so emoji count as two.
Message quota and pricing: what is free, and where it differs by country
The Messaging API is free to call, but LINE Official Account plans limit how many push-type messages you can send each month. LINE's pricing page gives Japan as its example:
| Japan (excluding tax) | Communication Plan | Light Plan | Standard Plan |
|---|---|---|---|
| Monthly fee | Free | JPY 5,000 | JPY 15,000 |
| Free messages per month | Up to 200 | Up to 5,000 | Up to 30,000 |
| Additional messages | Not available | Not available | Up to JPY 3 each, falling with volume |
Other markets have their own plans and prices. LINE links to separate pricing pages for Japan, Taiwan, Thailand and a page for other regions, so check the one for the country where you registered the account rather than copying numbers from a blog. Some rules hold everywhere:
- Replies are free. Only push, multicast, narrowcast and broadcast count. A support bot that only answers users who message first can run on the free plan indefinitely.
- Counting is per recipient, not per request. A push with four message objects to a group of five people counts as five messages.
- Undeliverable messages don't count. Messages to users who blocked you, or to IDs that don't exist, aren't charged.
- Hitting the cap is a hard stop. Further pushes fail with 429 You have reached your monthly limit until the month resets or you change plans. A large narrowcast can reserve quota while it is in progress, so you can hit this error with messages apparently left.
You can check where you stand with GET /v2/bot/message/quota and GET /v2/bot/message/quota/consumption. Our LINE Messaging API limits page keeps the quotas, rate limits and size caps on one screen.
Errors you will meet during setup, and what each means
These are the responses new LINE bots hit most in the first week. Each links to its page in our LINE error code directory, which has the full cause list and fixes.
| Response | Usual cause in a new bot |
|---|---|
| 401 Authentication failed | Token from another channel, a truncated token, or a long-lived token that was reissued |
| 400 Invalid reply token | Token used twice, used after about a minute, or a test with a made-up token |
| 403 Access to this API is not available | The endpoint needs a plan or approval your account doesn't have |
| 429 Too Many Requests | A loop or load test exceeding the per-endpoint rate limit |
| 429 monthly limit | Free push messages used up; replies still work |
| 413 Payload Too Large | A request body over 2 MB, usually inlined content that should be a URL |
| 500 Internal Server Error | A fault on LINE's side; retry with backoff, and with a retry key for pushes |
| Webhook request timeout | Your handler does its work before returning 200 |
Rate limits are per endpoint and per channel, on a token-bucket basis. Most endpoints allow 2,000 requests per second, but some are far lower: broadcast and narrowcast are limited to 60 requests per hour, and webhook endpoint settings to 1,000 per minute. LINE's guidelines also forbid load-testing your bot through the LINE Platform, so build a separate test harness if you need one. Every response includes an X-Line-Request-Id. Log it, because LINE says it doesn't provide logs on request and that ID is how you trace a specific call. The chatbot API rate limiting guide covers backoff patterns that apply here too.
Before you go live: a ten-point checklist
- The provider is owned by your company, with at least two admins.
- Signature verification runs on the raw body, compares in constant time, and rejects missing headers.
- The handler returns 200 within 2 seconds and processes events from a queue.
- Events are deduplicated by
webhookEventId, and unknown event types are ignored, not errors. - Use webhook is on; greeting and auto-reply messages are off, or deliberately kept.
- Replies go out within seconds; slow answers show the loading animation, and late ones fall back to push.
- Every push sends an
X-Line-Retry-Key, and 409 on a retry is treated as success. - You know your plan's free-message quota and alert before it runs out.
- The access token lives in a secret store, with a rotation plan (v2.1) or an IP allowlist (long-lived).
- Webhook redelivery and error statistics are enabled, and you log request IDs for every API call.
Group chats need one more decision: whether the bot answers every message or only mentions. A bot that replies to every line in a busy group gets removed fast. If something still goes wrong after launch, our LINE troubleshooting guide walks the causes in the order they happen.
Where a LINE bot earns its place in a business
LINE matters because of where people already are. LY Corporation, which runs LINE, reported that LINE passed 100 million monthly users in Japan in December 2025 (LY Corporation history). LINE also publishes separate Official Account pricing for Taiwan and Thailand. For a business selling into those countries, a LINE account often does the job that WhatsApp or SMS does elsewhere: it is where customers expect to ask a question or get an update.
The pricing model shapes what works best:
- Customer support and FAQs are cheapest, because customers start the conversation and replies are free. A bot that answers order, delivery and opening-hours questions handles volume without touching the quota.
- Bookings and reservations suit the rich menu plus a LIFF form: tap Book, pick a time, get a Flex confirmation card.
- Order and delivery notifications are pushes, so they count. Budget them against your plan, or ask customers to reply to opt in so updates can ride on replies where possible.
- Campaigns use narrowcast to segments of friends, with the recipient minimums and rate limits that come with it.
Whatever the use, plan the handoff to a person. A bot that answers routine questions and passes everything else to a human agent with the context attached is the pattern that holds up; our human handoff guide covers how to design that step. For market-by-market strategy in Japan, Thailand, Taiwan and Indonesia, see LINE chatbots for Asia-Pacific business.
Running LINE next to your other channels
Building a LINE bot by hand is a good weekend project. Running one in production means owning token rotation, signature checks, the reply-or-push decision, redelivery and quota alerts, and then doing the same again for every other messaging app your customers use. Each platform solves the same problems with different names: compare this guide with Telegram's BotFather token or Meta's webhook handshake.
Conferbot's native LINE channel is coming soon; it isn't available to connect yet. Our LINE channel page will carry the details when it ships. In the meantime, the same no-code flow builder runs today on a website chat widget, WhatsApp, Telegram and Messenger, with answers from your knowledge base, live chat handover and one shared inbox across every channel. Each of those channels is available on every plan, including Free.
Start free with Conferbot - the free plan includes 600 conversations a month and needs no credit card, so you can have the same flow answering on your website and WhatsApp this afternoon, while you build the LINE side by hand. See what the free plan includes or compare paid plans.
If you are building a LINE bot by hand today, keep the order simple: Official Account, Messaging API, token, raw-body signature check, Verify, Use webhook, auto-reply off, then a reply within the minute. Most stuck bots skipped one of those, and the error directory tells you which.
Was this article helpful?
Build and deploy in 10 minutes. No coding needed.
How to Make a LINE Bot FAQ
Everything you need to know about chatbots for how to make a line bot.
About the Author
The Conferbot team writes about building, deploying, and improving AI chatbots.
View all articlesRelated Articles
From the reference shelf
Fact-checked reference pages and free tools for the platform this article covers.