How to Add a ChatGPT Chatbot to Any PHP Website — Step by Step (2026)
A complete, working tutorial that takes you from zero to a fully functional AI chatbot running on your PHP site. No frameworks required — just plain PHP, cURL, and the OpenAI API.
Adding an AI chatbot to your PHP project is one of the most impressive features you can demonstrate — whether it is a final year project, a freelance client site, or a personal portfolio. The OpenAI API makes this possible in less than 30 minutes with plain PHP, no complex frameworks required.
This tutorial builds a fully working chatbot from scratch. By the end you will have a floating chat widget that sits on any page of your PHP site, sends messages to the OpenAI API, and streams intelligent responses back to users in real time.
What You Need Before Starting
- A PHP project running on XAMPP, WAMP, or any web server (PHP 7.4+)
- An OpenAI account (free to create at platform.openai.com)
- cURL enabled in PHP (it is on by default in XAMPP/WAMP)
- Basic knowledge of PHP and HTML — no advanced skills needed
gpt-4o-mini (the model we use in this tutorial) costs $0.15 per 1 million input tokens and $0.60 per 1 million output tokens. A typical chatbot message uses around 200–400 tokens total, meaning you can send roughly 2,500 messages for just $0.15. New OpenAI accounts also get $5 in free credits — enough to test your chatbot thousands of times before paying a cent.
Step 1 — Get Your OpenAI API Key
Go to platform.openai.com and sign up. No credit card is required to create an account — you get $5 in free credits automatically.
After logging in, click your profile → API Keys → Create new secret key. Give it a name like “php-chatbot”. Copy the key immediately — you cannot view it again after closing the window.
Save it in a text file on your computer for now. In a later step we will put it in a config file on your server. Never paste your API key into public GitHub repositories — anyone who finds it can use it and charge to your account.
Step 2 — Project File Structure
We will add just 3 files to your existing PHP project. This keeps the chatbot self-contained and easy to add to any existing project:
your-php-project/
│
├── index.php ← your existing main page
├── config.php ← NEW: stores your API key (never commit this)
├── chatbot.php ← NEW: PHP backend that calls OpenAI API
└── chatbot-widget.php ← NEW: the chat UI and JavaScript (include anywhere)
You will include chatbot-widget.php at the bottom of any page where you want the chatbot to appear — just one line of code per page.
Step 3 — The PHP Backend (chatbot.php)
This is the most important file. It receives a message from the user, sends it to the OpenAI API, and returns the AI response. Here is the complete code:
<?php
// ============================================================
// config.php — Store your API key here
// IMPORTANT: Never upload this file to GitHub or share it
// Add config.php to your .gitignore file
// ============================================================
define('OPENAI_API_KEY', 'sk-your-api-key-here'); // Replace with your real key
// The model to use — gpt-4o-mini is cheapest and fast enough for chatbots
define('OPENAI_MODEL', 'gpt-4o-mini');
// Customise this to make the bot specific to your project
// For example: "You are a helpful assistant for an ISP management system..."
define('SYSTEM_PROMPT', 'You are a helpful assistant on this website.
Answer questions clearly and concisely.
If you do not know something, say so honestly.');
// Max tokens in the AI response (roughly 150 tokens = ~100 words)
define('MAX_TOKENS', 500);
?>
<?php
// ============================================================
// chatbot.php — Receives user message, calls OpenAI, returns response
// Called via JavaScript fetch() from the chat widget
// ============================================================
require_once 'config.php';
// Only allow POST requests
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit(json_encode(['error' => 'Method not allowed']));
}
// Set JSON response header
header('Content-Type: application/json');
// Get and sanitise the incoming data
$input = json_decode(file_get_contents('php://input'), true);
if (!isset($input['message']) || empty(trim($input['message']))) {
echo json_encode(['error' => 'No message provided']);
exit;
}
$user_message = trim(htmlspecialchars($input['message'], ENT_QUOTES, 'UTF-8'));
// Get conversation history from the request (to maintain context)
$history = isset($input['history']) ? $input['history'] : [];
// Build the messages array for the OpenAI API
// System prompt comes first, then the conversation history, then the new message
$messages = [
['role' => 'system', 'content' => SYSTEM_PROMPT]
];
// Add previous messages (limit to last 10 to control token usage)
$recent_history = array_slice($history, -10);
foreach ($recent_history as $msg) {
if (isset($msg['role']) && isset($msg['content'])) {
$messages[] = [
'role' => in_array($msg['role'], ['user','assistant']) ? $msg['role'] : 'user',
'content' => htmlspecialchars($msg['content'], ENT_QUOTES, 'UTF-8')
];
}
}
// Add the new user message
$messages[] = ['role' => 'user', 'content' => $user_message];
// Build the request payload for OpenAI
$payload = json_encode([
'model' => OPENAI_MODEL,
'messages' => $messages,
'max_tokens' => MAX_TOKENS,
'temperature' => 0.7, // 0 = very consistent, 1 = more creative
]);
// Call the OpenAI Chat Completions API using cURL
$ch = curl_init('https://api.openai.com/v1/chat/completions');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . OPENAI_API_KEY,
],
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($ch);
$curl_error = curl_error($ch);
$http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Handle cURL errors (e.g. no internet connection)
if ($curl_error) {
echo json_encode(['error' => 'Connection error: ' . $curl_error]);
exit;
}
// Handle non-200 responses from OpenAI
if ($http_status !== 200) {
$error_data = json_decode($response, true);
$error_msg = isset($error_data['error']['message'])
? $error_data['error']['message']
: 'API error (HTTP ' . $http_status . ')';
echo json_encode(['error' => $error_msg]);
exit;
}
// Parse the OpenAI response
$data = json_decode($response, true);
if (!isset($data['choices'][0]['message']['content'])) {
echo json_encode(['error' => 'Unexpected response from API']);
exit;
}
// Extract the AI reply and token usage info
$bot_reply = $data['choices'][0]['message']['content'];
$tokens_used = isset($data['usage']['total_tokens']) ? $data['usage']['total_tokens'] : 0;
// Return the response to the JavaScript frontend
echo json_encode([
'reply' => $bot_reply,
'tokens_used' => $tokens_used,
]);
?>
<!-- ============================================================
chatbot-widget.php — Floating chat widget UI + JavaScript
Include this file at the bottom of any page where you want
the chatbot: <?php include 'chatbot-widget.php'; ?>
============================================================ -->
<!-- Floating chat button -->
<div id="cz-chat-bubble" onclick="czToggleChat()" title="Chat with AI Assistant"
style="position:fixed;bottom:24px;right:24px;width:54px;height:54px;
background:#0057b8;border-radius:50%;display:flex;align-items:center;
justify-content:center;cursor:pointer;z-index:9999;box-shadow:0 4px 16px rgba(0,87,184,.4);
font-size:1.4em;transition:transform .2s" onmouseover="this.style.transform='scale(1.1)'"
onmouseout="this.style.transform='scale(1)'">💬</div>
<!-- Unread badge -->
<div id="cz-badge" style="position:fixed;bottom:64px;right:22px;background:#ef4444;
color:#fff;border-radius:50%;width:18px;height:18px;display:flex;align-items:center;
justify-content:center;font-size:.65em;font-weight:700;z-index:10000;display:none">1</div>
<!-- Chat window -->
<div id="cz-chat-window" style="display:none;position:fixed;bottom:90px;right:24px;
width:340px;max-width:calc(100vw - 40px);background:#fff;border-radius:14px;
box-shadow:0 8px 40px rgba(0,0,0,.18);z-index:9998;overflow:hidden;
font-family:'Segoe UI',Tahoma,sans-serif;border:1px solid #e2e8f0">
<!-- Header -->
<div style="background:#0057b8;padding:14px 16px;display:flex;align-items:center;
justify-content:space-between">
<div style="display:flex;align-items:center;gap:10px">
<div style="width:34px;height:34px;background:rgba(255,255,255,.2);border-radius:50%;
display:flex;align-items:center;justify-content:center;font-size:1.1em">🤖</div>
<div>
<div style="color:#fff;font-weight:700;font-size:.9em">AI Assistant</div>
<div style="color:rgba(255,255,255,.75);font-size:.72em">Powered by ChatGPT</div>
</div>
</div>
<button onclick="czToggleChat()" style="background:none;border:none;color:rgba(255,255,255,.8);
font-size:1.2em;cursor:pointer;padding:4px 8px;border-radius:4px" title="Close">✕</button>
</div>
<!-- Messages area -->
<div id="cz-messages" style="height:280px;overflow-y:auto;padding:14px;
display:flex;flex-direction:column;gap:10px;background:#f8faff">
<!-- Welcome message -->
<div style="background:#fff;border:1px solid #e2e8f0;border-radius:10px 10px 10px 2px;
padding:10px 13px;font-size:.84em;color:#444;max-width:88%;line-height:1.55">
👋 Hi! I am your AI assistant. How can I help you today?
</div>
</div>
<!-- Input area -->
<div style="padding:12px;border-top:1px solid #e8edf5;background:#fff;display:flex;gap:8px">
<input id="cz-input" type="text" placeholder="Type your message..."
style="flex:1;padding:9px 13px;border:1.5px solid #e2e8f0;border-radius:8px;
font-family:'Segoe UI',sans-serif;font-size:.84em;outline:none;color:#1c1c1c"
onfocus="this.style.borderColor='#0057b8'" onblur="this.style.borderColor='#e2e8f0'"
onkeypress="if(event.key==='Enter')czSendMessage()">
<button id="cz-send-btn" onclick="czSendMessage()"
style="background:#0057b8;color:#fff;border:none;border-radius:8px;padding:9px 14px;
font-size:.84em;font-weight:700;cursor:pointer;white-space:nowrap;transition:background .2s"
onmouseover="this.style.background='#003d8a'" onmouseout="this.style.background='#0057b8'">
Send
</button>
</div>
<!-- Footer -->
<div style="padding:6px 12px 8px;text-align:center;font-size:.68em;color:#aaa;background:#fff">
Powered by OpenAI GPT-4o mini
</div>
</div>
<script>
var czHistory = [];
var czOpen = false;
function czToggleChat() {
czOpen = !czOpen;
document.getElementById('cz-chat-window').style.display = czOpen ? 'block' : 'none';
document.getElementById('cz-badge').style.display = 'none';
if (czOpen) document.getElementById('cz-input').focus();
}
function czAddMessage(text, isUser) {
var msgs = document.getElementById('cz-messages');
var div = document.createElement('div');
div.style.cssText = isUser
? 'background:#0057b8;color:#fff;border-radius:10px 10px 2px 10px;padding:10px 13px;font-size:.84em;max-width:88%;align-self:flex-end;margin-left:auto;line-height:1.55'
: 'background:#fff;border:1px solid #e2e8f0;border-radius:10px 10px 10px 2px;padding:10px 13px;font-size:.84em;color:#333;max-width:88%;line-height:1.55';
div.textContent = text;
msgs.appendChild(div);
msgs.scrollTop = msgs.scrollHeight;
return div;
}
function czShowTyping() {
var msgs = document.getElementById('cz-messages');
var div = document.createElement('div');
div.id = 'cz-typing';
div.style.cssText = 'background:#fff;border:1px solid #e2e8f0;border-radius:10px 10px 10px 2px;padding:10px 13px;font-size:.84em;color:#999;max-width:88%;font-style:italic;line-height:1.55';
div.textContent = 'Thinking...';
msgs.appendChild(div);
msgs.scrollTop = msgs.scrollHeight;
}
function czRemoveTyping() {
var t = document.getElementById('cz-typing');
if (t) t.remove();
}
function czSendMessage() {
var input = document.getElementById('cz-input');
var btn = document.getElementById('cz-send-btn');
var text = input.value.trim();
if (!text) return;
// Add user message to UI and history
czAddMessage(text, true);
czHistory.push({ role: 'user', content: text });
input.value = '';
btn.disabled = true;
btn.textContent = '...';
czShowTyping();
// Send to PHP backend
fetch('chatbot.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: text, history: czHistory })
})
.then(function(res) { return res.json(); })
.then(function(data) {
czRemoveTyping();
if (data.error) {
czAddMessage('Sorry, something went wrong: ' + data.error, false);
} else {
czAddMessage(data.reply, false);
czHistory.push({ role: 'assistant', content: data.reply });
}
})
.catch(function() {
czRemoveTyping();
czAddMessage('Could not connect to the server. Please try again.', false);
})
.finally(function() {
btn.disabled = false;
btn.textContent = 'Send';
document.getElementById('cz-input').focus();
});
}
</script>
<?php
// Your existing PHP code above ...
?>
<!DOCTYPE html>
<html>
<head>
<title>Your PHP Project</title>
</head>
<body>
<!-- Your existing page content -->
<h1>Welcome to my project</h1>
<!-- ADD THIS ONE LINE at the bottom of every page where you want the chatbot -->
<?php include 'chatbot-widget.php'; ?>
</body>
</html>
Step 4 — Preview the Chatbot (Live Demo)
This is what the finished chatbot looks like and how it behaves. Click the demo below to try it — this version uses simulated responses to show you the UI and conversation flow:
Demo uses simulated responses — real chatbot connects to OpenAI API
Step 5 — Customise the System Prompt for Your Project
The SYSTEM_PROMPT in config.php is what makes the chatbot specific to your website. Instead of a generic assistant, you can make it an expert on your particular project. Here are ready-to-use system prompts for common student projects:
For an ISP Management System
define('SYSTEM_PROMPT', 'You are a helpful support assistant for an ISP Management System.
You help administrators and customers with questions about:
- Internet plans and pricing
- Monthly billing and invoice queries
- Account management and password resets
- Network troubleshooting and router setup
- Stock and equipment availability
Keep your answers concise, friendly, and professional.
If a customer has a billing dispute, ask them to contact billing@yourisp.com.
Do not reveal any internal system configuration or passwords.');
For a Hospital Management System
define('SYSTEM_PROMPT', 'You are a patient support assistant for a hospital management system.
You can help with:
- Appointment booking information and available departments
- General information about visiting hours and hospital location
- Explaining what documents patients need to bring
- Directing patients to the correct department
IMPORTANT: Never provide medical diagnoses or specific medical advice.
Always recommend patients speak directly with a doctor for medical concerns.
For emergencies, always direct users to call emergency services immediately.');
For an E-Commerce Website
define('SYSTEM_PROMPT', 'You are a customer service assistant for our online store.
You help customers with:
- Finding products and checking availability
- Understanding our return and refund policy (14-day returns, full refund)
- Tracking order status (ask for their order number)
- Shipping information (free shipping over $50, 3-5 business days standard)
- Payment methods accepted (credit card, PayPal, bank transfer)
Always be friendly, helpful, and solution-focused.
If a customer is upset, acknowledge their frustration first before solving the problem.');
Step 6 — Test Locally and Deploy
Testing on Localhost (XAMPP / WAMP)
- Place all three files in your project folder inside
htdocs(XAMPP) orwww(WAMP) - Replace
'sk-your-api-key-here'inconfig.phpwith your real OpenAI API key - Add
<?php include 'chatbot-widget.php'; ?>at the bottom of yourindex.php - Open
http://localhost/your-project/in your browser - You should see the 💬 blue button in the bottom-right corner — click it and send a message
Deploying to a Live Server (Hostinger, cPanel, etc.)
- Upload all three files to your hosting via FTP or File Manager
- Verify PHP cURL is enabled — open cPanel → PHP Extensions and check that
curlis ticked - Make sure
config.phpis not accessible directly from a browser — add this to your.htaccess:
# Block direct browser access to config.php
<Files "config.php">
Order Allow,Deny
Deny from all
</Files>
config.php on the server side. Add a rate limiting check to chatbot.php so users cannot spam the API and rack up charges on your account.
API Cost Calculator
Use this calculator to estimate your monthly OpenAI API cost based on expected usage:
💰 Estimate Your Monthly Cost
OpenAI Model Comparison — Which to Use
| Model | Cost (per 1M tokens) | Speed | Best For |
|---|---|---|---|
| gpt-4o-mini Recommended | $0.15 input / $0.60 output | Very fast | Chatbots, customer support, student projects |
| gpt-4o | $2.50 input / $10.00 output | Fast | Complex reasoning, image understanding |
| gpt-4.1 | $2.00 input / $8.00 output | Fast | Long documents, coding assistance |
| gpt-4.1-mini | $0.40 input / $1.60 output | Very fast | Balanced quality and cost |
gpt-4o-mini. It is fast, cheap, and more than capable enough for a support chatbot. The $5 free credits you get with a new OpenAI account will last you through months of testing.
How to Extend This Chatbot
Create a chat_logs table and INSERT each message with the user’s IP, timestamp, and message. This lets you review what users are asking and improve your system prompt over time. Also useful for showing conversation history across sessions.
If your PHP project already has user login, pass the logged-in user’s name and account details in the system prompt so the bot can give personalised answers: “The user’s name is Ahmed. Their current plan is 10 Mbps at $25/month.”
Store a message count per session in $_SESSION and check it in chatbot.php before calling the API. If a user sends more than 20 messages in an hour, return a polite error instead of calling OpenAI — this protects your credits.
Include your project’s key data in the system prompt — for example, your product list, FAQ content, or pricing table. The bot can then answer specific questions about your actual project data, not just generic answers.
The OpenAI API supports streaming responses where tokens arrive one by one (like you see on ChatGPT.com). This makes the chatbot feel more alive. Implement it using PHP’s flush() and JavaScript’s ReadableStream — more advanced but very impressive for a demo.
Frequently Asked Questions
Do I need Composer or any PHP library to use the OpenAI API?
No. This tutorial uses PHP’s built-in cURL library to call the OpenAI API directly — no Composer, no external libraries, no dependencies. This makes it easier to understand and deploy on any shared hosting. There is an official OpenAI PHP SDK available via Composer if you prefer that approach for larger projects, but for a chatbot like this, plain cURL is perfectly sufficient.
How much will this cost to run?
Using gpt-4o-mini, each conversation exchange (a user message plus the AI response) typically uses 200–500 tokens and costs between $0.0001 and $0.0004. That means 1,000 conversations cost roughly $0.10–$0.40. For a student project or small website with under 100 daily users, you are looking at a few dollars per month at most. New OpenAI accounts receive $5 in free credits — enough for 10,000–30,000 test messages.
My chatbot is not responding. What should I check?
Check these in order: (1) Make sure your API key in config.php is correct and has no extra spaces. (2) Open your browser’s Developer Tools → Network tab, click Send, and check the response from chatbot.php — it will show the exact error message. (3) Make sure cURL is enabled in your PHP setup — run <?php phpinfo(); ?> and search for “cURL”. (4) Check if you have credits remaining in your OpenAI account at platform.openai.com/usage.
Can I use this on a shared hosting plan?
Yes. Any shared hosting that supports PHP 7.4+ with cURL enabled will work — Hostinger, Namecheap, Bluehost, InMotion, etc. Most shared hosts enable cURL by default. If it is disabled, you can usually turn it on from the PHP Extensions section in cPanel, or ask your hosting support to enable it.
Can I use a different AI model instead of GPT?
Yes. The code in this tutorial is specifically for OpenAI’s API. To use Google Gemini instead, you would change the API endpoint and request format to match Google’s API. To use Anthropic’s Claude, you change the endpoint to https://api.anthropic.com/v1/messages with a slightly different request structure. The frontend chatbot widget JavaScript works the same regardless — only chatbot.php needs to change.
How do I make the bot remember who the logged-in user is?
If your PHP project has session-based login, you can include the user’s details in the system prompt dynamically. In config.php, instead of a fixed string, set the system prompt in chatbot.php using session variables: $system = "You are helping " . $_SESSION['user_name'] . " who has the " . $_SESSION['plan_name'] . " plan.". The bot will then tailor its answers to that specific user.
Is this a good feature to add to my final year project?
Absolutely. An AI chatbot is one of the highest-impact features you can add to any project in 2026. It demonstrates understanding of APIs, server-side scripting, JSON data exchange, and modern AI integration — all of which are highly relevant to real-world development. Examiners consistently rate AI-integrated projects higher. Make sure you can explain how the OpenAI API works, what tokens are, and how the conversation history is managed — these are the likely viva questions on this feature.
The Complete Code — All Files in One Place
For quick reference, here is a summary of the 3 files you need and what each one does:
- config.php — stores your API key and system prompt. Keep this private, never commit to GitHub.
- chatbot.php — the PHP backend. Receives user messages via POST, calls OpenAI API, returns JSON response.
- chatbot-widget.php — the complete chat UI and JavaScript. Include it on any page with one line.
Related Tutorials on Codezips
Last updated: April 2026. OpenAI model names and pricing verified from platform.openai.com. Always check the official OpenAI documentation for the latest model availability and pricing.

