A multilingual WhatsApp chatbot built with Python Flask Claude AI and WhatsApp Cloud API
Technology

How to Build a WhatsApp Multilingual Chatbot with Python, Flask & Claude AI (Step-by-Step Guide)

What’s Inside?

Introduction

Imagine messaging a WhatsApp multilingual chatbot in Swahili, Arabic, or French and getting an instant reply in the same language.

For companies serving global audiences, language barriers are one of the biggest obstacles to good customer support. Yet most chatbots still respond only in English.

WhatsApp has over 3.3 billion active users worldwide. A large portion of them do not primarily use English. From Swahili speakers in East Africa to Arabic speakers in the Middle East, global messaging is multilingual.

If you’re building a WhatsApp chatbot for a global audience, responding only in English means leaving most of your potential users behind. A bot that automatically detects what language someone is speaking and replies in kind feels like magic and with modern AI, it’s surprisingly straightforward to build.

In this tutorial, you’ll learn how to build a WhatsApp multilingual chatbot using Python and Claude AI. It is an easy to follow step-by-step guide to deploying an AI-powered bot that automatically detects and responds in any language.

What You’ll use to Build the WhatsApp Multilingual Chatbot

In this tutorial, you’ll build a production-ready WhatsApp multilingual chatbot using:

By the end, you’ll have a working bot you can deploy and share and a solid foundation to add more features. Some of the features will include:

  • Detecting the user’s language automatically
  • Replying naturally using Claude AI
  • Remembering the conversation context
  • Working inside WhatsApp in real time
  • Supporting languages like English, Swahili, Arabic, French, Spanish, and more

You could even include a sample conversation:

Sample WhatsApp Conversation

Prerequisites

Before you start, make sure you have the following:

You do not need a paid WhatsApp Business account to follow this tutorial. Meta provides a free test number with sandbox access that is more than enough for development.

How the WhatsApp Multilingual Chatbot Works: An Architecture Overview

Before writing any code, it helps to understand the complete flow. We have added a high-level flow that can help you visualise how the WhatsApp chatbot is structured:

A WhatsApp Chatbot Architecture

Every time someone sends your bot a message, Meta sends an HTTP POST request to your server (the web hook). Your Flask app processes it, calls Claude AI with the message and some context, and sends the reply back through the WhatsApp API.

The key insight for multilingual support is the system prompt you give Claude. Rather than manually detecting languages with a library and routing to different handlers, you simply tell Claude: ‘Always detect the language of the user’s message and respond in that same language.‘ Claude handles the rest.

The Project Setup: WhatsApp Multilingual Chatbot with Python

Now that you understand the architecture, let’s start building the bot step by step.

1. Create the Project Structure

When creating the project structure, you must organize your files as follows to keep the app modular as shown below:

A WhatsApp Chatbot Project Structure

2. Install Dependencies

Create a virtual environment and install the required packages as shown below:

A guide on installation of dependencies for a WhatsApp chatbot

3. Set Up Environment Variables

Create a .env file at the root of your project. Always remember to never commit this file to GitHub as it contains your secret API keys. We don’t want anyone on the internet to me messing around with your secret keys.

A guide on how to set up environment files in Python

You’ll find WHATSAPP_ACCESS_TOKEN and WHATSAPP_PHONE_NUMBER_ID in the Meta Developer Console under WhatsApp → API Setup. VERIFY_TOKEN is a string you choose yourself and it must match what you configure in the Meta Dashboard.

Setting Up the WhatsApp Business API

Step 1: Create a Meta App

To create a Meta app you will need to follow the steps outlined below:

  1. Go to https://developers.facebook.com and log in.
  2. Click Create App → Choose Business type → Name your app.
  3. On the dashboard, scroll to find the WhatsApp product and click Set Up.

Step 2: Get Your Credentials

Upon successful creation of the app in the WhatsApp section of your app, go to API Setup. You will see the following:

  • A temporary access token (valid for 24 hours during development)
  • A Phone Number ID for the test number Meta provides
  • The test WhatsApp number you can message from your personal phone

For production, you will need a permanent system user token. However, for this tutorial the temporary token is fine.

Step 3: Configure the Webhook

Once you have your temporary access token, phone number ID and the test WhatsApp number you can message you will need to configure the webhook. A webhook is a lightweight, event-driven HTTP callback that allows one application to automatically push real-time data to another system when a specific event occurs. This webhook is where Meta sends messages to your server. You will need a public HTTPS URL. During development, you can use ngrok as shown below:

Steps on how to sonfigure a WhatsApp webhook

ngrok will give you a URL like https://abc123.ngrok.io. In the Meta Developer Console:

  • Go to WhatsApp → Configuration → Webhook
  • Set Callback URL to: https://abc123.ngrok.io/webhook
  • Set Verify Token to match your VERIFY_TOKEN env variable
  • Subscribe to the messages event

Building the WhatsApp Multilingual Chatbot with Python: Writing the Code

The Flask App Factory (main.py)

We will start with the Flask application factory. This pattern makes the app easier to test and deploy because it separates configuration from runtime.

A Flask Application

The Webhook Routes (routes.py)

The webhook has two endpoints:

  • GET for verification
  • POST for receiving messages
Webhook routes configurations

WhatsApp API Helpers (whatsapp.py)

This module handles all communication with the Meta Graph API sending messages and parsing incoming payloads as shown below:

WhatsApp API Helpers

The Multilingual Brain (chatbot.py)

This is the heart of the application. We use a Python deque to store the last 10 exchanges (20 items) per user to maintain context without overflowing memory. Here is where language detection and reply generation happen as shown below:

the multilingual brain

Language Detection Nuances

While Claude handles multilingual responses gracefully, there are a few edge cases to be aware of:

Short Messages Are Ambiguous

A one-word message like ‘Hi’ or ‘Ok’ could be in any language. Our system prompt tells Claude to default to English in these cases, which is usually the safest fallback. However in a real product, you could track the last detected language per user and use that as a hint.

Code Switching

Many people naturally mix languages (e.g., Swahili and English, French and Wolof). Claude handles this gracefully if you send a mixed-language message, it typically replies in the dominant language or matches the pattern of the input.

Regional Variants

Claude is aware of regional variants like Brazilian Portuguese vs European Portuguese, or Mexican Spanish vs Castilian Spanish. If the user’s writing style suggests a regional variant, Claude tends to mirror it.

Sensitive Languages

Some languages, like Arabic and Hebrew, are right-to-left. WhatsApp handles the rendering on the user’s device automatically, so your bot just needs to return the correct Unicode text which Claude does.

Conversation Memory

The chatbot maintains per-user conversation history using Python’s deque with a maximum length as shown below:

conversation memory of a WhatsApp chatbot

This means that:

  • Each user has their own independent conversation thread
  • The bot remembers the last 10 message pairs (20 items = 10 exchanges)
  • Memory resets when the server restarts (in-memory only)

For a production system, you would replace the in-memory store with Redis or a database. The interface is the same just swap the deque for a Redis list or a database table.

production db update for a WhatsApp chatbot

Testing Your WhatsApp Multilingual Chatbot

A thorough test strategy covers three layers: automated unit tests that run without any API calls, manual curl tests that simulate real WhatsApp payloads, and structured logging so you can see exactly what your bot receives and sends at every step.

Unit Tests with Pytest

We have the project available on our Github repo (https://github.com/RootedDreamsBlog/WhatsApp-Multilingual-Chatbot) which you can fork to get started. The project includes a full test suite. You can run tests with:

running unit tests

You should see output like this when all tests pass:

Test cases output samples

The tests cover webhook verification, message parsing, conversation memory, and the chatbot reply function (mocked to avoid real API calls). Claude API calls are mocked in tests so they run instantly without consuming API credits or needing a live connection.

Adding Structured Logging

Good logging is essential for a webhook app you cannot set a breakpoint when Meta sends you a live message. Add a logger at every key step in routes.py:

sample structured logging

With this in place, every exchange produces clean, timestamped terminal output:

Logs

Manual Testing via curl

Simulate any incoming WhatsApp message without a real phone; great for testing specific languages or edge cases before going live:

manual testing

The bot should detect French and reply in French. Run the same command with different message bodies to verify language detection. Here are example inputs and expected outputs:

LanguageYou SendExpected Reply Language
FrenchBonjour, pouvez-vous m’aider ?French
SpanishHola, puedes ayudarme con algo?Spanish
SwahiliHabari, unaweza kunisaidia?Swahili
ArabicHello in Arabic scriptArabic
PortugueseOla, pode me ajudar com uma pergunta?Portuguese
EnglishHi there, can you help me?English
ShonaMhoro, ungandibatsira here?Shona

Testing Conversation Memory

Send a sequence of curl requests from the same phone number to verify that the bot carries context across messages:

testing conversation memory

Health Check

The /health endpoint lets you instantly confirm your server is running useful in deployment pipelines and uptime monitors:

health check

Deploying the WhatsApp Multilingual Chatbot to Production

Railway is the fastest way to deploy a Python app with a public URL. To do so you can follow the steps outlined below:

  • Push your code to GitHub
  • Go to railway.app → New Project → Deploy from GitHub Repo
  • Select your repository
  • In the Variables tab, add all your .env variables
  • Railway auto-detects the Procfile and deploys

Railway will give you a permanent public URL like https://whatsapp-bot-production.up.railway.app which you can use as your webhook URL in the Meta Developer Console (instead of the ngrok URL).

Option B: Render

Render is another excellent free-tier option. You can do so by following the steps below:

  • Connect your GitHub repo at render.com
  • Choose Web Service → Python environment
  • Set Start Command to: gunicorn “app.main:create_app()” –bind 0.0.0.0:$PORT
  • Add environment variables in the Render dashboard

Option C: AWS / GCP / Azure

For enterprise deployments, you must containerize the app with Docker and deploy to any cloud provider. The Procfile doubles as a Heroku-compatible deployment config, and the app is stateless by design.

Security Best Practices

When you move from development to a public-facing production bot, security is non-negotiable. WhatsApp bots handle real user conversations, and your webhook is publicly accessible on the internet. Here is what you need to lock down before going live.

1. Never Commit .env Files to GitHub

Your .env file contains secret API keys. A single accidental git push can expose your WhatsApp token and Anthropic key, allowing anyone to send messages as your bot or burn through your API credits.

git commits

2. Validate WhatsApp Webhook Signatures

Anyone who discovers your webhook URL can send fake POST requests to it injecting arbitrary messages into your bot. Meta signs every legitimate request with an HMAC-SHA256 signature using your App Secret. You should verify this signature before processing any payload.

validate whatsapp signatures

Add WHATSAPP_APP_SECRET to your .env file. You find this value in Meta Developer Console → Your App → Settings → Basic → App Secret.

3. Always Use HTTPS

Meta’s webhook will only POST to HTTPS endpoints it will refuse plain HTTP. During development, ngrok provides HTTPS automatically. In production, Railway and Render provide HTTPS by default. If you’re deploying to a raw server (e.g. an EC2 instance), use Nginx with a free Let’s Encrypt certificate:

always use https

4. Rate-Limit Users

Without rate limiting, a single user (or a bot hammering your endpoint) can send thousands of messages per minute, exhausting your Anthropic API credits and potentially hitting WhatsApp’s own messaging limits. A simple per-user rate limiter using a dictionary of timestamps is enough for most use cases:

rate limiting users

For production, use Redis with a sliding window algorithm instead of the in-memory dict this survives server restarts and works across multiple instances.

5. Store Secrets Securely in Production

A .env file works for local development, but in production your secrets should live in your hosting platform’s secret manager not in a file that could be accidentally exposed:

store secrets securely in production

6. Input Validation

Although Claude handles arbitrary text gracefully, you should still validate and sanitize inputs at the webhook layer enforce a maximum message length to avoid unexpectedly large payloads, and skip processing messages that are clearly empty or whitespace-only:

input validation

Security Checklist

PracticeWhy It MattersStatus
.env in .gitignorePrevents accidental key exposure on GitHubMust have
Webhook signature verificationBlocks spoofed requests from bad actorsMust have
HTTPS onlyEncrypts traffic; required by MetaMust have
Per-user rate limitingPrevents abuse and API credit exhaustionMust have
Secrets in platform vaultSafer than file-based secrets in productionRecommended
Input length validationPrevents oversized payloads from crashing appRecommended
Rotate tokens regularlyLimits damage if a token is ever leakedRecommended

Additional Feature Ideas

Once your bot is running, here are some powerful extensions:

Voice Message Transcription

WhatsApp users frequently send voice notes. You can extend the bot to transcribe them using Whisper (OpenAI) or another STT service, then pass the transcribed text to Claude.

Image Understanding

Claude is multimodal. When a user sends an image, you can download it from the WhatsApp media API, base64-encode it, and pass it to Claude’s vision endpoint along with a prompt to describe or analyze it.

Persistent User Profiles

Store user preferences (preferred language, name, location) in a database so the bot personalizes responses across sessions.

Handover to Human Agent

Detect phrases like ‘speak to a human’ in any language and route the conversation to a live agent platform like Intercom or Freshdesk.

Rate Limiting

Add per-user rate limiting to prevent abuse. A simple Redis-based token bucket works well for this.

Quick Reference

Just to help you with a quick checklist of what you need to build your very first Python WhatsApp chatbot, the tables below outline the key files you need and the environment variables.

Key Files

FilePurpose
app/main.pyFlask app factory which is the entry point
app/routes.pyWebhook GET (verify) and POST (receive message)
app/whatsapp.pySend messages and parse incoming payloads
app/chatbot.pyClaude AI integration with conversation memory
.envSecret API keys (never commit to GitHub)
ProcfileTells Railway/Heroku how to start the app
tests/test_app.pyFull pytest test suite

Environment Variables Reference

VariableWhere to Get ItRequired
WHATSAPP_ACCESS_TOKENMeta Developer Console → WhatsApp → API SetupYes
WHATSAPP_PHONE_NUMBER_IDMeta Developer Console → WhatsApp → API SetupYes
VERIFY_TOKENChoose your own secure stringYes
ANTHROPIC_API_KEYconsole.anthropic.com → API KeysYes
PORTSet to 5000 locally, auto-set by host in productionNo

Common Errors & How to Fix Them

This section covers the most frequent issues developers encounter when building and running this bot. Each error includes what it looks like, why it happens, and exactly how to fix it to help you resolve them should you encounter any of the errors.

1. Webhook Verification Fails (403 Forbidden)

What you see

Meta shows a red error after clicking ‘Verify and Save’ in the Developer Console, or your terminal logs a 403 response to the GET /webhook request.

Why it happens

Meta sends a GET request to your /webhook endpoint containing a hub.verify_token query parameter. Your app must return the hub.challenge value only if the token matches. A 403 almost always means the VERIFY_TOKEN in your .env doesn’t exactly match what you entered in the Meta Dashboard even a single extra space or different casing will break it.

How to fix it

  • Open your .env file, copy the VERIFY_TOKEN value exactly (don’t retype it)
  • In Meta Developer Console, go to WhatsApp → Configuration → Webhook and paste that exact value into the Verify Token field
  • If running locally, confirm ngrok is active and the Callback URL in Meta matches your current ngrok tunnel
webhook validation fails

2. Messages Arrive but No Reply Is Sent

What you see

You message the bot, your server logs show the POST /webhook request arriving and returning 200, but the WhatsApp user receives nothing. No error is thrown in your Python app.

Why it happens

The most common causes are:

  • Your WhatsApp access token has expired Meta’s development tokens expire every 24 hours;
  • The WHATSAPP_PHONE_NUMBER_ID is wrong; or
  • In the test environment, the recipient’s number has not been added to the list of allowed recipients.

How to fix it

  • Refresh your access token: Meta Developer Console → WhatsApp → API Setup → copy the new token into .env
  • Verify WHATSAPP_PHONE_NUMBER_ID it is a 15-digit number like 102391234567890, not your personal phone number
  • In the Meta test sandbox, go to API Setup → ‘To’ field and add your personal WhatsApp number to the allowed recipients list
messages arrive but no reply is sent

3. Claude API AuthenticationError (401)

What you see

Claude API Authentication Error

Why it happens

The ANTHROPIC_API_KEY environment variable is missing, contains a typo, or load_dotenv() is being called after the Anthropic client is instantiated (so the client initializes with an empty key).

How to fix it

  • Check that ANTHROPIC_API_KEY is present and correct in your .env file
  • Make sure load_dotenv() is called at the very top of main.py, before importing app.routes (which imports chatbot.py, which creates the client)
  • Verify the key is active at console.anthropic.com → API Keys
Claude API Authentication Error resolution

4. ngrok Tunnel Expires or URL Changes

What you see

The bot worked yesterday but today no messages come through. Your ngrok terminal shows a new URL starting with a different random subdomain, but Meta still has the old URL saved.

Why it happens

Free ngrok sessions expire after a few hours and generate a brand-new random URL every time you restart the tunnel. Meta’s webhook configuration still points to the old URL.

How to fix it

  • Every time you restart ngrok, copy the new HTTPS URL and update it in Meta Developer Console → WhatsApp → Configuration → Webhook
  • Sign up for a free ngrok account to get a stable subdomain that never changes
  • Long-term: deploy to Railway or Render to get a permanent production URL (see Deploying to Production)
ngrok Tunnel Expires or URL Changes

5. Bot Sends Duplicate Replies

What you see

A user sends one message and receives two or three identical replies from the bot. This happens intermittently and is worse on slow connections.

Why it happens

WhatsApp Cloud API uses an at-least-once delivery model. If your server doesn’t return a 200 OK within roughly 5 seconds, Meta retries the POST request. If your Claude API call takes longer than that which it can on first load or under load your handler processes the same message twice.

How to fix it

Return 200 immediately, then handle the message in a background thread. Also track processed message IDs to skip duplicates:

Bot Sends Duplicate Replies

6. Bot Always Responds in English

What you see

You send a message in French, Swahili, or Spanish, but the bot replies in English every time. The language detection appears to be completely ignored.

Why it happens

Either the system prompt isn’t strong enough in its language instruction, the message is too short for confident detection (a single word like ‘Salut’ or ‘Hola’ is ambiguous), or the system prompt isn’t being passed correctly to the API call.

How to fix it

  • Test with full sentences ‘Bonjour, j’ai une question sur mon compte’ is far easier to detect than ‘Salut’
  • Strengthen the language instruction in your SYSTEM_PROMPT
  • Add a console.log / print to verify the system prompt is being passed to client.messages.create

# Stronger system prompt; be very explicit:

SYSTEM_PROMPT = “””

You are a multilingual WhatsApp assistant.

ABSOLUTE RULE: You MUST detect the language of the user’s message

and respond ENTIRELY in that same language. No exceptions.

– User writes in French   → respond in French

– User writes in Swahili  → respond in Swahili

– User writes in Arabic   → respond in Arabic

– User writes in Spanish  → respond in Spanish

Only default to English if the message is a single character or

completely unrecognizable. Never mix languages in a single response.

“””

7. Port Already in Use on Startup

What you see

Port Already in Use on Startup

Why it happens

A previous Flask instance that wasn’t properly stopped is still holding port 5000. This commonly happens after pressing Ctrl+Z (which suspends instead of terminating) or after a crash.

How to fix it

Port Already in Use on Startup resolution

8. Claude Returns 529 ‘Overloaded’ Error

What you see

Claude Returns 529 'Overloaded' Error

Why it happens

The Anthropic API is experiencing unusually high traffic. This is a transient error that typically resolves within seconds to a few minutes. It is not caused by anything in your code.

How to fix it

Add exponential backoff retry logic so your bot gracefully retries rather than surfacing an error to the user:

Claude Returns 529 'Overloaded' Error

Quick Reference: Error Lookup Table

Symptom / Error CodeMost Likely CauseFirst Thing to Check
403 on webhook verifyVERIFY_TOKEN mismatchCompare .env token vs Meta Dashboard
200 OK but no reply sentExpired token or wrong phone IDRefresh token in Meta Console
401 AuthenticationErrorMissing or invalid ANTHROPIC_API_KEYCheck .env + load_dotenv() order
Meta error code 190WhatsApp access token expiredRegenerate in Meta API Setup
Duplicate replies to userServer too slow → Meta retryReturn 200 immediately, process async
Bot always replies in EnglishWeak system prompt or short inputStrengthen language rule in SYSTEM_PROMPT
529 OverloadedAnthropic API high traffic (transient)Add retry with exponential backoff
Address already in useOld Flask process still on port 5000lsof -ti:5000 | xargs kill -9

Conclusion

You have now built a fully functional, production-ready WhatsApp chatbot that speaks your users’ language literally. In just a few hundred lines of Python, you have:

  • A verified, secure webhook that Meta can send messages to
  • Automatic language detection and multilingual responses via Claude AI
  • Per-user conversation memory that maintains context across messages
  • Clean error handling and a full test suite
  • A deployment setup that works on Railway, Render, or any cloud provider

The multilingual capability is what makes this bot genuinely useful for global applications. Whether your users write to you in Swahili, Arabic, French, or Shona, they get a response that feels natural and local.

From here you can extend it with:

  • Voice message transcription
  • Image analysis
  • Product search
  • Customer support automation

With just a few additional integrations, this bot can become the backbone of a global messaging platform.

If you want the full code it is available on GitHub at https://github.com/RootedDreamsBlog/WhatsApp-Multilingual-Chatbot. If you have questions, open an issue or reach out directly. Happy building!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.