iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
To build a WhatsApp chatbot in Python, connect a WhatsApp Business Account to Meta’s Cloud API, expose an HTTPS webhook for incoming events, and use Python to send replies through the API. The basic bot below reads a text message and returns a deterministic response; it is a starting point, not a complete production service.
What you need before writing the bot
Meta’s WhatsApp Cloud API is the official WhatsApp Business Platform API. You need a Meta business portfolio, a WhatsApp Business Account (WABA), and a business phone number. These are platform prerequisites, not Python packages. Follow Meta’s Cloud API setup guide to create or select the assets and obtain the phone-number ID and access token used by your application.
You also need a public HTTPS endpoint to receive webhook notifications. A development server running only on your computer’s localhost cannot receive Meta’s requests directly. For local development, use a secure tunnel if you have one; for deployment, use an endpoint reachable over HTTPS with a valid certificate. Meta’s webhook documentation explains the callback setup and verification requirements.
Choose how to call the API
For a small tutorial bot, direct HTTPS requests from Python make the request and response flow visible. A third-party wrapper is another option: PyWa documents integrations with Flask and FastAPI. It is an abstraction over the platform, not an official Meta Python SDK. Choose a wrapper if its documented integration fits your application; otherwise, direct requests avoid adding a framework dependency.
#1 Best Overall
Set up credentials and a Python project
Use Meta’s setup flow to obtain the phone-number ID and an access token. Meta’s WhatsApp Business Platform Postman collection notes that user access tokens expire after 24 hours; system-user tokens may be configured to last up to 60 days or permanently, depending on configuration. Check the current token settings for your account rather than treating any lifetime as universal. Keep tokens, app secrets, and webhook verification strings out of source code and public repositories. If a credential is exposed, revoke or rotate it through Meta’s account settings.
Create a virtual environment, then install Flask and Requests:
Rank #2
python -m venv .venv
# macOS or Linux:
source .venv/bin/activate
# Windows PowerShell:
.venvScriptsActivate.ps1
pip install Flask requests
Set the configuration as environment variables in your local shell or deployment environment. Use the current Graph API version shown in Meta’s documentation; the example deliberately reads it from configuration instead of freezing a version string in code.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallexport WHATSAPP_TOKEN="your_access_token"
export PHONE_NUMBER_ID="your_phone_number_id"
export VERIFY_TOKEN="a_private_verification_string"
export GRAPH_API_VERSION="current_version_from_meta_docs"
On Windows PowerShell, set the same variables with $env:WHATSAPP_TOKEN="your_access_token", replacing the variable name as needed. Do not commit a real token or verification string to Git.
Create the webhook and reply handler
Meta uses a GET request to verify the callback URL and POST requests to deliver webhook notifications. Keep those responsibilities separate. The following Flask example verifies the callback, ignores status-only or unsupported events, extracts inbound text defensively, and sends one simple reply.
import os
import requests
from flask import Flask, request
app = Flask(__name__)
VERIFY_TOKEN = os.environ["VERIFY_TOKEN"]
WHATSAPP_TOKEN = os.environ["WHATSAPP_TOKEN"]
PHONE_NUMBER_ID = os.environ["PHONE_NUMBER_ID"]
GRAPH_API_VERSION = os.environ["GRAPH_API_VERSION"]
@app.get("/webhook")
def verify_webhook():
mode = request.args.get("hub.mode")
token = request.args.get("hub.verify_token")
challenge = request.args.get("hub.challenge")
if mode == "subscribe" and token == VERIFY_TOKEN and challenge:
return challenge, 200
return "Verification failed", 403
@app.post("/webhook")
def receive_webhook():
payload = request.get_json(silent=True) or {}
for entry in payload.get("entry", []):
for change in entry.get("changes", []):
value = change.get("value", {})
for message in value.get("messages", []):
if message.get("type") != "text":
continue
sender = message.get("from")
text = message.get("text", {}).get("body", "").strip()
if sender and text:
reply_to_text(sender, text)
return "EVENT_RECEIVED", 200
def reply_to_text(recipient, incoming_text):
normalized = incoming_text.casefold()
if normalized in {"hello", "hi", "hey"}:
reply = "Hello! How can I help?"
else:
reply = "Thanks for your message. What would you like help with?"
url = (
f"https://graph.facebook.com/{GRAPH_API_VERSION}/"
f"{PHONE_NUMBER_ID}/messages"
)
headers = {
"Authorization": f"Bearer {WHATSAPP_TOKEN}",
"Content-Type": "application/json",
}
body = {
"messaging_product": "whatsapp",
"to": recipient,
"type": "text",
"text": {"body": reply},
}
response = requests.post(url, headers=headers, json=body, timeout=15)
response.raise_for_status()
Run the app locally with flask --app app run --port 5000 if the file is named app.py. Your webhook URL will use the public HTTPS address that forwards to this server, followed by /webhook. Do not treat the built-in Flask development server as a production deployment.
What the handler does—and does not—process
Webhook notifications contain nested account, change, messaging-product, metadata, and event data. An inbound text appears under a message object, while a status notification can report states such as sent, delivered, read, failed, or deleted. The loop above only processes text messages; it safely skips other message types and events with no messages. Consult Meta’s webhook components reference when expanding event handling.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →The example sends the response during request handling to keep the tutorial short. A deployed bot should acknowledge webhook deliveries promptly and move slower work—such as external lookups or lengthy business logic—to a background queue. Design processing to tolerate duplicate deliveries, for example by recording processed message IDs; exact delivery and retry behavior can depend on the platform’s current implementation.
Best Value
Configure and verify the webhook in Meta
- Make the callback reachable. Start the Flask app and expose its
/webhookroute at a public HTTPS URL with a valid certificate. - Enter the callback details. In the Meta app’s WhatsApp webhook configuration, provide the callback URL and the same private verification string used for
VERIFY_TOKEN. - Complete verification. Meta sends a GET request with verification parameters. The app must return the challenge only when the mode and verification token match. A failed check commonly means the callback URL, token, route, or public reachability does not match.
- Subscribe to the WABA events. Subscribe the app to the WhatsApp Business Account and the message events your bot needs. Configuring the callback alone does not replace the WABA subscription.
- Send a test message. Check your server logs and confirm that the POST route receives the expected event. If no event arrives, recheck HTTPS reachability, the app’s WABA subscription, and the selected event fields.
Send messages through the Cloud API
The reply_to_text function posts to the messages endpoint associated with the phone-number ID. It authenticates with a bearer token and identifies WhatsApp as the messaging product. Meta’s current setup and API documentation should be used for the active Graph API version, endpoint details, and permissions; those can change, so the sample does not prescribe a permanent version number or permission list.
Understand the conversation-template rule
Under Meta’s WhatsApp Business Messaging Policy, a business may initiate a conversation only using an approved message template. A bot replying to a customer’s inbound message is different from a business-initiated message. If your product needs to contact a person first, create and use an approved template according to Meta’s current policy and API instructions.
Check pricing before launch
WhatsApp Business API fees follow Meta’s rate card and pricing rules, which Meta may update. Costs depend on the applicable current pricing terms; check the rate card for your market before estimating operating expenses rather than relying on an old static price.
Quick Recap
Prepare the chatbot for real users
- Handle more message types: provide an intentional fallback for images, buttons, interactive replies, and other unsupported content instead of silently assuming every inbound message is text.
- Validate incoming data: check that the expected objects and fields exist, and avoid logging message contents or credentials unnecessarily.
- Check API failures: catch request timeouts and HTTP errors, record useful diagnostic details without exposing secrets, and avoid retrying indefinitely.
- Prevent duplicate work: persist inbound message IDs and make business actions idempotent so repeated webhook deliveries do not repeat an order or payment action.
- Separate development from production: use a stable HTTPS deployment, managed secret storage, monitored logs, and an operational process for rotating tokens.
- Revisit Meta’s documentation: confirm current endpoint versions, access settings, webhook fields, policy rules, and regional rates whenever you change or launch the integration.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

