LINE LIFF Development Guide: Build LIFF Apps for Thailand (2026)
1 May 2026 · Updated 5 October 2026 · by Yunmin Shin
What Is LINE LIFF and Why Does It Matter in Thailand?
LINE LIFF (LINE Front-end Framework) lets you run your own web app inside the LINE app. You build an ordinary web page, register it as a LIFF app, and customers open it from your LINE Official Account — already signed in with LINE, with nothing to download.
That matters in Thailand because LINE is where customers already talk to businesses. LINE reports more than 50 million users in the country, and for most Bangkok clinics, salons and restaurants the LINE OA chat is the booking channel. The problem is that it is usually run by hand: a staff member reads each message, checks a calendar, and types back available slots.
A LIFF app replaces that loop. The customer taps "Book" in the rich menu, picks a service and a time on a real web form, and gets a confirmation pushed back into the same chat. It is self-service at midnight and doesn't depend on whoever is watching the inbox.
LIFF vs LINE MINI App vs LINE Official Account
These three get mixed up constantly, including in quotes from agencies:
- LINE Official Account (LINE OA) — the business account customers add as a friend and chat with. It hosts the rich menu and sends messages through the Messaging API.
- LIFF app — your web app, opened inside LINE. Registered under a LINE Login channel. No review needed.
- LINE MINI App — a LIFF app that has passed LINE's review, which unlocks extra distribution and features. Worth it for consumer brands that want discovery inside LINE; unnecessary for most SMEs that drive traffic from their own OA.
A typical booking system uses all three pieces together: the OA is the front door, the rich menu is the button, the LIFF app is the booking form, and the Messaging API sends the confirmation.
How Do You Set Up a LIFF App?
Step 1: Create a provider and a LINE Login channel in the LINE Developers Console. LIFF apps are added to a LINE Login channel (or a LINE MINI App channel), not to the Messaging API channel your OA uses — link the two to the same provider so user IDs match (more on that below).
Step 2: Add a LIFF app. Set:
- Endpoint URL — your HTTPS web app, e.g.
https://book.yourclinic.com/. HTTPS is mandatory. - Size — Compact, Tall or Full. Use Full for multi-step flows like booking; Compact and Tall open as a sheet over the chat and are better for one-tap actions.
- Scopes — tick
profile(needed forgetProfile()) andopenid(needed forgetIDToken()).
Step 3: Note your LIFF ID. It looks like 1234567890-AbCdEfGh. The shareable entry URL is https://liff.line.me/1234567890-AbCdEfGh.
Step 4: Install the SDK:
npm install @line/liff
Step 5: Initialise LIFF before calling any other method:
import liff from "@line/liff";
await liff.init({ liffId: process.env.NEXT_PUBLIC_LIFF_ID! });
if (!liff.isLoggedIn()) {
// Only happens in an external browser — inside LINE the user is already logged in.
liff.login();
}
In Next.js, call liff.init() inside a useEffect in a client component, because LIFF needs browser APIs. Show a loading state until it resolves — initialisation can take a noticeable moment on a mid-range Android phone inside LINE's in-app browser, and a flash of "please log in" reads as broken to a first-time user.
How Do You Get the User's Profile and userId?
Once initialised, LIFF gives you the logged-in LINE user:
const profile = await liff.getProfile();
// profile.userId -> "U4af4980629..." (U + 32 hex characters)
// profile.displayName -> "Somchai"
// profile.pictureUrl -> profile image URL (may be missing)
Use userId as the stable key for the customer in your database. In a clinic booking schema that is a patients.line_user_id column: create the record the first time someone opens the app, and every visit after that you already know who they are.
Two details that catch people out:
- A userId is unique per provider, not per person globally. The same customer has a different userId under a different provider. Put your LIFF channel and your Messaging API channel under the same provider, or you will not be able to push messages to the IDs your LIFF app collected.
getProfile()fails if theprofilescope isn't enabled on the LIFF app, or if you call it beforeliff.init()resolves.
We cover the identity calls in more depth — including the full verification request — in LIFF getProfile and userId: getting and verifying a LINE user ID.
How Do You Verify the User Server-Side?
Never trust a userId posted from the browser — anyone can send any string. Send the ID token instead:
const idToken = liff.getIDToken(); // requires the openid scope
await fetch("/api/appointments", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ idToken, treatmentId, slot }),
});
On the server, verify it with LINE before you write anything:
const res = await fetch("https://api.line.me/oauth2/v2.1/verify", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ id_token: idToken, client_id: process.env.LINE_LOGIN_CHANNEL_ID! }),
});
if (!res.ok) return new Response("Invalid token", { status: 401 });
const { sub: userId } = await res.json(); // sub is the verified userId
For a booking system this is not optional: with an unverified ID, anyone could view or cancel another customer's appointment.
How Do You Build a Booking Flow Inside LIFF?
A clinic, salon or restaurant booking flow is usually four screens:
- What — treatment, service or party size.
- Where and who — branch, and staff member if it matters.
- When — available slots, calculated server-side from existing bookings, opening hours and staff schedules.
- Confirm — write the booking and immediately push a LINE message confirming it.
Send the confirmation as a LINE push message rather than relying on the LIFF screen. Most people close the LIFF window the moment they tap "Confirm" and expect the confirmation to appear in the chat — exactly where a staff reply used to arrive. The same channel then carries the reminder the day before, which is where most of the no-show reduction comes from.
Make the flow resumable. Test what happens when the user swipes back, or LINE's close button interrupts step 3: keep the in-progress state (in the URL or sessionStorage) so they can pick up where they left off.
For restaurants specifically, see online restaurant booking systems in Bangkok; for the broader LINE OA setup, see LINE booking systems for Thai businesses.
How Does the Rich Menu Fit In?
The rich menu — the image menu pinned to the bottom of the chat with your OA — is the entry point into the LIFF app. Give it a few large tap targets ("Book now", "Services & prices", "Talk to staff") and point "Book now" at your LIFF URL. You can append a path and query (https://liff.line.me/{liffId}/branch/siam) to land the user on a specific branch's calendar instead of a generic start screen.
Keep it to a handful of buttons. The rich menu renders small on a typical Android phone, and eight tiny icons guarantee mis-taps.
How Do You Share Content from LIFF?
liff.shareTargetPicker() lets a user send a message from your app to their own friends and groups:
if (liff.isApiAvailable("shareTargetPicker")) {
await liff.shareTargetPicker([
{ type: "text", text: "I just booked at [Clinic] — here's the link: https://liff.line.me/..." },
]);
}
Combine it with a referral code per user and you have a trackable word-of-mouth channel native to LINE. A recommendation from a friend in a LINE group carries far more trust than an ad, particularly for treatments people judge by results on someone they know.
What Are the LIFF Limitations?
- No browser push notifications. Use the Messaging API from your server instead.
- In-app browser quirks. Viewport height differs between iOS and Android LINE, and with the LIFF header shown or hidden. Test on both.
- External browsers behave differently. Outside LINE the user must log in via
liff.login(), and some APIs (likeshareTargetPickeron older clients) may be unavailable — checkliff.isInClient()andliff.isApiAvailable(). - Payments. Asking someone to type a full card number inside an in-app browser converts poorly. For Thai customers a PromptPay QR is usually the better path — see PromptPay QR payment integration.
How Much Does a LIFF App Cost to Build?
LIFF itself is free. What you pay for is the development and, separately, your LINE OA plan's message quota for pushed messages. A booking flow with an admin dashboard and LINE notifications sits in our Lead System tier — see our fixed prices — and a restaurant version is described on our restaurant booking page.
Get a free quote. We reply within 24 hours.
Frequently asked questions
What is LINE LIFF?
LIFF (LINE Front-end Framework) is LINE's platform for running your own web app inside the LINE app. You host an ordinary HTTPS web page, register it as a LIFF app in the LINE Developers Console, and users open it from a chat, a rich menu or a link — already signed in with their LINE account, with no app to install.
What is the difference between a LIFF app and a LINE MINI App?
Technically both are web apps built on the LIFF SDK. A LINE MINI App is a LIFF app that goes through LINE's review process and can then appear in LINE's own discovery surfaces and use extra features. A plain LIFF app needs no review and is opened from your own LINE Official Account, links or QR codes — which is what most Thai SMEs actually need.
Where do I find my LIFF ID?
In the LINE Developers Console, open the LINE Login (or LINE MINI App) channel the LIFF app was added to and go to the LIFF tab. Each app is listed with a LIFF ID in the form 1234567890-AbCdEfGh and a LIFF URL of the form https://liff.line.me/1234567890-AbCdEfGh.
Can I get the user's LINE userId inside a LIFF app?
Yes. With the profile scope enabled, liff.getProfile() returns userId, displayName and pictureUrl. Do not trust a userId the browser sends to your server, though — send the ID token from liff.getIDToken() instead and verify it server-side with LINE's verify endpoint.
How much does it cost to build a LIFF booking app in Thailand?
LINE does not charge for LIFF itself. The cost is the development: a booking flow with an admin dashboard and LINE notifications sits in our Lead System tier, from ฿50,000, agreed as a fixed price before work starts. Pushed LINE messages count against your LINE Official Account plan's message quota.
Want this working for your business in Thailand?
We build and run the same systems on 16 live sites of our own. Tell us your business — we reply within 24 hours with what the search data shows.