The practical way to build an AI customer-service bot for LINE or KakaoTalk is to host the webhook yourself on a VPS in Tokyo, Japan (for LINE) or Seoul, South Korea (for KakaoTalk), and let it call an LLM API such as OpenAI, Claude or Gemini to draft replies. JUSTG offers Tokyo and Seoul cloud VPS with native local IPs from $19.99/mo, with 1 IPv4 + free IPv6 and automatic deployment after payment, which covers the HTTPS endpoint, the automation tool and the conversation database on one server. This guide shows two builds: self-hosted n8n (low-code) and a small Python webhook, plus HTTPS, latency, rate limits, local logs under Japan's APPI and Korea's PIPA, and hand-off to a human.
- Locations: Tokyo, Japan (close to LINE users) and Seoul, South Korea on the KT network (close to KakaoTalk users).
- IP type: native Japanese or Korean IPv4, plus free IPv6; useful as a fixed source IP for allowlists.
- AI APIs: OpenAI, Claude and Gemini are officially available in Japan and South Korea; JUSTG tested its Tokyo and Seoul IPs with all three in October 2026.
- Price: JUSTG Tokyo Cloud VPS and JUSTG Seoul Cloud VPS from $19.99/mo; plans up to 7 cores / 24 GB at $169.99/mo.
- Moscow, Russia is not suitable for bots that call these AI APIs (not available in Russia).
How a LINE or KakaoTalk AI bot works
The messenger platform sends each user message to your HTTPS webhook, your server asks the LLM for a reply, and sends it back through the platform's API.
- A customer writes to your LINE Official Account or Kakao Talk Channel.
- LINE (Messaging API) or Kakao (Kakao i Open Builder skill) POSTs JSON to your URL, e.g.
https://api.example.com/line. - Your server verifies the request, stores the message, adds your FAQ or product context, and calls the LLM API.
- The answer goes back: LINE uses a reply API with a short-lived reply token; Kakao expects the answer in the HTTP response itself.
- Keywords or low confidence trigger a hand-off to a human agent.
| Item | LINE (Japan) | KakaoTalk (Korea) |
|---|---|---|
| Bot framework | LINE Messaging API, LINE Official Account | Kakao i Open Builder skill server, Kakao Talk Channel |
| How you answer | Return HTTP 200 at once, then call the reply API with the reply token | Return the answer in the webhook response (skill JSON, version 2.0) |
| Time pressure | Reply token expires quickly; reply as soon as the LLM finishes | About 5 seconds per skill request; longer answers need Kakao's callback option where available |
| Request check | HMAC-SHA256 signature in X-Line-Signature | Restrict the path, add a secret header or token, check bot ID |
| Recommended JUSTG location | JUSTG Tokyo Cloud VPS | JUSTG Seoul Cloud VPS |
Why host the bot in Tokyo or Seoul
Hosting next to the messenger and its users keeps round trips short, and both countries are supported regions for the major LLM APIs.
- Latency budget. The LLM call usually takes 1-4 seconds. Saving 100-200 ms on each hop to LINE or Kakao servers matters, especially under Kakao's ~5-second limit.
- AI API availability. OpenAI, Anthropic and Google support Japan and South Korea. Moscow, Russia is not suitable for this bot, because these APIs are not available in Russia. Providers can change policies at any time, and account and payment checks still apply.
- Fixed native IP. Your VPS has a stable Japanese or Korean IP that you can allowlist in your own CRM, order system or database firewall.
- Data residency. Conversation logs stay on a server in the same country as your customers, which simplifies privacy notices.
Option A: self-hosted n8n with Docker Compose
n8n is a good choice when non-developers need to edit the bot's flow, prompts and integrations in a visual editor.
On a JUSTG Tokyo or Seoul Cloud VPS with Docker installed, point bot.example.com to the server IP (for example 203.0.113.20) and run:
mkdir -p /opt/n8n && cd /opt/n8n
echo "N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)" > .env && chmod 600 .env
cat > docker-compose.yml <<'YML'
services:
n8n:
image: docker.n8n.io/n8nio/n8n:latest
env_file: .env
environment:
- N8N_HOST=bot.example.com
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://bot.example.com/
- GENERIC_TIMEZONE=Asia/Tokyo
- TZ=Asia/Tokyo
ports: ["127.0.0.1:5678:5678"]
volumes: ["n8n_data:/home/node/.n8n"]
restart: unless-stopped
volumes:
n8n_data:
YML
docker compose up -d
Then put n8n and the Python app (option B) behind Caddy, which issues Let's Encrypt certificates automatically:
apt install -y caddy
cat > /etc/caddy/Caddyfile <<'CFG'
bot.example.com {
reverse_proxy 127.0.0.1:5678
}
api.example.com {
reverse_proxy 127.0.0.1:8000
}
CFG
systemctl reload caddy
ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp && ufw enable
In the n8n editor, build this flow: Webhook node (POST, path line) → Code node to verify the LINE signature → IF node for hand-off keywords → OpenAI or Anthropic chat node with your system prompt → HTTP Request node to https://api.line.me/v2/bot/message/reply. Set the webhook node to respond immediately so LINE gets HTTP 200 straight away. For Kakao, use "Respond to Webhook" with the skill JSON at the end of the flow. Store API keys only in n8n Credentials, which are encrypted with N8N_ENCRYPTION_KEY.
Option B: a small Python webhook skeleton
A 70-line FastAPI app is easier to version-control and test, and handles both LINE and Kakao.
# app.py - pip install fastapi uvicorn httpx openai
import base64, hashlib, hmac, os, sqlite3, time
import httpx
from fastapi import FastAPI, Request, BackgroundTasks, HTTPException
from openai import OpenAI
LINE_SECRET = os.environ["LINE_CHANNEL_SECRET"].encode()
LINE_TOKEN = os.environ["LINE_CHANNEL_TOKEN"]
llm = OpenAI() # reads OPENAI_API_KEY
db = sqlite3.connect("/data/chat.db", check_same_thread=False)
db.execute("CREATE TABLE IF NOT EXISTS log(ts, channel, user_id, role, text)")
SYSTEM = "You are the support assistant of Example Shop. Answer briefly in the user's language. If unsure, say a staff member will follow up."
HANDOFF = ("担当者", "オペレーター", "상담원", "human", "staff")
app = FastAPI()
def log(ch, uid, role, text):
db.execute("INSERT INTO log VALUES (?,?,?,?,?)", (time.time(), ch, uid, role, text)); db.commit()
def answer(text):
r = llm.chat.completions.create(model="gpt-4o-mini", max_tokens=400,
messages=[{"role": "system", "content": SYSTEM}, {"role": "user", "content": text}])
return r.choices[0].message.content
def handle_line(event):
uid, text = event["source"]["userId"], event["message"]["text"]
log("line", uid, "user", text)
if any(k in text for k in HANDOFF):
reply = "スタッフにおつなぎします。少々お待ちください。"
else:
reply = answer(text)
log("line", uid, "bot", reply)
httpx.post("https://api.line.me/v2/bot/message/reply", timeout=10,
headers={"Authorization": f"Bearer {LINE_TOKEN}"},
json={"replyToken": event["replyToken"], "messages": [{"type": "text", "text": reply[:4900]}]})
@app.post("/line")
async def line_webhook(req: Request, bg: BackgroundTasks):
body = await req.body()
sig = base64.b64encode(hmac.new(LINE_SECRET, body, hashlib.sha256).digest()).decode()
if not hmac.compare_digest(sig, req.headers.get("x-line-signature", "")):
raise HTTPException(403)
for ev in (await req.json()).get("events", []):
if ev.get("type") == "message" and ev["message"].get("type") == "text":
bg.add_task(handle_line, ev) # return 200 at once, work in background
return "OK"
@app.post("/kakao")
async def kakao_skill(req: Request):
data = await req.json()
uid = data["userRequest"]["user"]["id"]; text = data["userRequest"]["utterance"]
log("kakao", uid, "user", text)
reply = answer(text) # must finish within Kakao's ~5 s skill timeout
log("kakao", uid, "bot", reply)
return {"version": "2.0", "template": {"outputs": [{"simpleText": {"text": reply[:1000]}}]}}
Run it as a systemd service listening only on localhost:
mkdir -p /data && chmod 700 /data
python3 -m venv /opt/bot/venv && /opt/bot/venv/bin/pip install fastapi uvicorn httpx openai
# put LINE_CHANNEL_SECRET, LINE_CHANNEL_TOKEN, OPENAI_API_KEY in /opt/bot/.env (chmod 600)
cat > /etc/systemd/system/bot.service <<'UNIT'
[Unit]
Description=LINE/Kakao AI bot
After=network-online.target
[Service]
WorkingDirectory=/opt/bot
EnvironmentFile=/opt/bot/.env
ExecStart=/opt/bot/venv/bin/uvicorn app:app --host 127.0.0.1 --port 8000
Restart=always
[Install]
WantedBy=multi-user.target
UNIT
systemctl daemon-reload && systemctl enable --now bot
In the LINE Developers console set the webhook URL to https://api.example.com/line and click Verify; in Kakao i Open Builder register https://api.example.com/kakao as a skill and link it to your fallback block. Check that bad signatures are rejected quickly:
curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" -X POST https://api.example.com/line \
-H "x-line-signature: invalid" -d '{"events":[]}'
# expected: 403 and a time well under 1 s
journalctl -u bot -fHTTPS, latency and rate limits
Both platforms require a public HTTPS endpoint with a valid certificate, and both punish slow responses.
- Certificates: use a real domain and a trusted certificate (Let's Encrypt via Caddy). Self-signed certificates and bare IPs are not accepted as webhook URLs.
- Answer fast: acknowledge LINE webhooks immediately and do the LLM work in the background. For Kakao, use a fast model, cap
max_tokens, and keep prompts short so the reply fits in the time limit. - Messenger limits: the LINE Messaging API has rate limits per endpoint, and push messages count toward your plan's monthly message quota, while replies to user messages do not. Prefer replies over pushes.
- LLM limits: handle HTTP 429 from the LLM with a polite fallback text and retries with backoff; set provider budgets and alerts.
- Abuse protection: limit messages per user per minute in your code, and cap input length before calling the LLM.
Keeping conversation logs locally: APPI and PIPA basics
Chat logs contain personal information, so store them on your own server, keep them only as long as needed, and tell customers how AI is used.
- Japan (APPI, Act on the Protection of Personal Information): state the purpose of use, keep data secure, and note that sending personal data to a provider in another country (for example a US-based LLM API) has extra disclosure or consent requirements.
- Korea (PIPA, Personal Information Protection Act): collect only what you need with a clear notice or consent, disclose overseas transfer and processors, and delete data after the retention period.
- Mask phone numbers, emails and order IDs before sending text to the LLM where possible.
- Encrypt the disk backups, restrict SSH, and keep the SQLite or Postgres database off the public internet.
- This is general information, not legal advice; ask a local counsel for your exact case.
Human hand-off that customers actually like
A good bot knows when to stop: route to a person on request, on complaints, and on anything involving money or accounts.
- Trigger words such as "担当者", "オペレーター", "상담원" or "human", repeated failed answers, or refund and payment topics.
- Mark the user as "human mode" in your database so the bot stops answering, and notify staff by email, Slack or LINE WORKS.
- Staff reply from LINE Official Account Manager chat or the Kakao channel's consultation chat; switch the user back to bot mode afterward.
- Tell customers business hours and expected wait times in the hand-off message.
Which JUSTG plan fits
A support bot is light on CPU; RAM depends on whether you run n8n and a database next to it.
| Setup | Suggested RAM | Location |
|---|---|---|
| Python webhook + SQLite, one channel | 1-2 GB | Tokyo for LINE, Seoul for Kakao |
| n8n + webhook + Postgres | 2-4 GB | Same country as most customers |
| Both LINE and Kakao, RAG over product docs | 4-8 GB | One VPS per country, or Tokyo for both |
Start with a JUSTG Tokyo Cloud VPS for LINE in Japan or a JUSTG Seoul Cloud VPS for KakaoTalk in Korea; both use Asia-optimized routes, and you can add extra IPs later via the Upgrade options on the service page. Custom configurations (more CPU, RAM, disk, bandwidth or IPs) are available on request: contact sales via ticket for a custom quote. More AI hosting scenarios are on our AI VPS page.
FAQ
What is the best server location for a LINE chatbot?
Tokyo, Japan, because LINE's main user base is in Japan and the major LLM APIs are officially available there. JUSTG Tokyo Cloud VPS provides a native Japanese IP from $19.99/mo, enough for a webhook plus n8n.
Can a KakaoTalk chatbot use ChatGPT or Claude?
Yes. A Kakao i Open Builder skill server can call the OpenAI, Claude or Gemini API and return the answer within Kakao's roughly 5-second limit. Hosting it on a JUSTG Seoul Cloud VPS keeps the round trip to Kakao short.
Does a LINE webhook need HTTPS?
Yes. LINE only accepts HTTPS webhook URLs with a valid certificate. Use a domain and a free Let's Encrypt certificate via Caddy or Nginx on your VPS.
Can I host the bot on a Moscow VPS?
Not if it calls OpenAI, Claude or Gemini, because these APIs are not available in Russia. Use JUSTG Tokyo or Seoul for the bot; JUSTG Moscow Cloud VPS is better suited to Russian-market workloads that do not depend on these APIs.
Launch your bot
With one small VPS you can answer LINE and KakaoTalk customers around the clock while keeping logs under your control. Order a JUSTG Tokyo Cloud VPS or a JUSTG Seoul Cloud VPS, follow the steps above, and our 24/7 support team is available via ticket.