Hosting

How to Host a PHP Website for Free (with a MySQL Database)

Where you can still host a PHP and MySQL website for free, a tested guestbook in index.php to put online today, the database host name trap that breaks most first uploads, and when it is time to move to paid hosting.

A PHP guestbook website running on free hosting with a MySQL database

Yes, you can still host a PHP website with a MySQL database for free. Free hosting is good for learning, a portfolio, a school project, or trying a script before you pay for anything. It is not good for a business, and the free hosts change their rules often, so it helps to know the limits before you start.

This guide shows where free PHP hosting still works, gives you a small tested guestbook to put online, walks through the upload step by step, and explains the one setting that breaks most first attempts.

Free hosting that runs PHP and MySQL

OptionWhat you getThe catch
InfinityFreeShared hosting with 5 GB of disk, up to 400 MySQL databases, a recent PHP version, free SSL, a free subdomain or your own domain, no ads on your siteDaily limits on visits and server use, limits on file size and number of files, no PHP mail(), no SSH
Oracle Cloud Free TierA whole Linux server, free for good, where you install PHP and MySQL yourselfYou manage everything, and free servers are often out of capacity. See our Oracle Cloud free VPS guide.
GitHub Pages, Netlify, VercelFree hosting for HTML, CSS and JavaScriptThey do not run PHP or MySQL, so they only suit static sites
000webhost–Closed in 2024. Old guides that recommend it are out of date.

Numbers as listed by InfinityFree in October 2026. The rest of this guide uses InfinityFree, because it gives you cPanel-style hosting with MySQL without a credit card, but the code works on any PHP host.

Try it: a guestbook in index.php

A guestbook is the smallest real PHP and MySQL website: a form, a database table, and a list. Visitors leave a message and everyone sees it. It is also a good test of free hosting, because it shows whether PHP, the database and sessions all work. Save the code below as index.php; the next section shows where the four database values come from.

<?php
// index.php: a guestbook with PHP and MySQL, to test free hosting.
// Fill in the four database values from your hosting's MySQL page.
$db = new PDO(
    'mysql:host=sql123.infinityfree.com;dbname=if0_12345678_guestbook;charset=utf8mb4',
    'if0_12345678',              // MySQL user name
    'your-mysql-password',       // MySQL password
    [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);

$db->exec('CREATE TABLE IF NOT EXISTS messages (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(60) NOT NULL,
    message VARCHAR(500) NOT NULL,
    created DATETIME NOT NULL
)');

session_start();
if (empty($_SESSION['token'])) {
    $_SESSION['token'] = bin2hex(random_bytes(16));
}

function e($text) {
    return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
}

$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name    = trim($_POST['name'] ?? '');
    $message = trim($_POST['message'] ?? '');

    if (!hash_equals($_SESSION['token'], $_POST['token'] ?? '')) {
        $error = 'Please reload the page and try again.';
    } elseif (($_POST['website'] ?? '') !== '') {
        $error = 'Spam check failed.';          // a hidden field that only bots fill in
    } elseif ($name === '' || $message === '') {
        $error = 'Please write your name and a message.';
    } else {
        $save = $db->prepare('INSERT INTO messages (name, message, created) VALUES (?, ?, NOW())');
        $save->execute([mb_substr($name, 0, 60), mb_substr($message, 0, 500)]);
        header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));   // a reload will not post twice
        exit;
    }
}

$messages = $db->query('SELECT name, message, created FROM messages ORDER BY id DESC LIMIT 50')->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Guestbook</title>
<style>
  body { font-family: system-ui, sans-serif; max-width: 640px; margin: 30px auto; padding: 0 16px; }
  input, textarea, button { width: 100%; box-sizing: border-box; padding: 10px; margin-top: 8px; font: inherit; }
  .hide { display: none; }
  .error { color: #b91c1c; }
  .msg { border-bottom: 1px solid #ddd; padding: 12px 0; }
  .msg small { color: #666; }
</style>
</head>
<body>
<h1>Guestbook</h1>

<form method="post">
  <?php if ($error): ?><p class="error"><?= e($error) ?></p><?php endif; ?>
  <input name="name" maxlength="60" placeholder="Your name" required>
  <textarea name="message" maxlength="500" rows="4" placeholder="Your message" required></textarea>
  <input class="hide" name="website" tabindex="-1" autocomplete="off">
  <input type="hidden" name="token" value="<?= e($_SESSION['token']) ?>">
  <button>Post message</button>
</form>

<?php foreach ($messages as $m): ?>
  <div class="msg">
    <strong><?= e($m['name']) ?></strong> <small><?= e($m['created']) ?></small>
    <p><?= nl2br(e($m['message'])) ?></p>
  </div>
<?php endforeach; ?>
</body>
</html>
PartWhat it does
new PDO('mysql:host=...')Connects to MySQL with the host, database, user and password from your hosting
CREATE TABLE IF NOT EXISTSMakes the messages table on the first visit, so there is no SQL to import
prepare() and execute()Prepared statements: what visitors type can never change your SQL
e() with htmlspecialcharsEvery message is escaped before it is shown, so a message containing <script> shows as text and never runs
The tokenA secret from the session in every form, so other websites cannot post to your guestbook
The hidden website fieldPeople never see it; spam bots fill in every field, and their posts are refused
mb_substrCuts names to 60 and messages to 500 characters, even if someone skips the form's limits
header('Location: ...')After saving, the page reloads with a normal visit, so pressing refresh does not post the message twice

Put it online on InfinityFree, step by step

  1. Create an account at InfinityFree and then a hosting account. Choose a free subdomain, or use a domain you own.
  2. Open the hosting account's Control Panel and then MySQL Databases. Create a database called guestbook.
  3. The MySQL page now shows four values: the MySQL host name (like sql123.infinityfree.com), the database name (like if0_12345678_guestbook), the user name (like if0_12345678) and the password (your hosting account password, shown in the client area). Put all four into the top of index.php.
  4. Open the File Manager (or connect with FileZilla using the FTP details from the client area) and go into the htdocs folder. That is your website's folder on InfinityFree, not public_html.
  5. Delete the default welcome file there, upload index.php, and open your subdomain in the browser. Post a message: if it appears, PHP and MySQL both work.
  6. In the client area, request the free SSL certificate for your domain so the site opens with https://.

The trap: the database host is not localhost

On most paid hosting the database host is localhost, and many tutorials and scripts take that for granted. On free hosting the database runs on a separate server, so localhost fails with SQLSTATE[HY000] [2002] or Connection refused. Always copy the host name from the MySQL page. The same goes for the prefix: the database is if0_12345678_guestbook, not guestbook.

Other first-upload errors are the same as on paid hosting, with fixes in our guide to uploading a website to cPanel.

What free hosting will not do

  • Send email with PHP's mail(). It is blocked to stop spam. Contact forms and password resets need an outside mail service through SMTP, for example with PHPMailer:
// Free hosts block PHP's mail(). Send through an outside mail service with PHPMailer instead:
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
$mail->isSMTP();
$mail->Host       = 'smtp.your-mail-provider.com';
$mail->SMTPAuth   = true;
$mail->Username   = 'you@yourdomain.com';
$mail->Password   = 'the-smtp-password';
$mail->SMTPSecure = 'tls';
$mail->Port       = 587;
  • Handle a traffic spike. When a site goes over the daily limits it is suspended until the next day, which is exactly when you have the most visitors.
  • Run scheduled jobs or long scripts. There is no SSH, and long-running PHP scripts are stopped.
  • Look professional. A free subdomain, no email at your own domain, and no promise of uptime are fine for a test, but not for customers.

When your site becomes real

Move to paid hosting when the site has regular visitors, takes payments or orders, or needs email. That is when these matter:

  • Cheap paid shared hosting with cPanel, email at your domain, daily backups and a sensible renewal price. Our guide on cheap web hosting shows what to compare.
  • A copy of the site to test changes on a subdomain, before the real site gets them
  • Security that a guestbook does not need: admin logins with locking after wrong passwords, safe file uploads, and spam protection on every form
  • A VPS only when you run software shared hosting does not allow, such as a chat or VPN server

Moving is easy: the guestbook, or any PHP site, runs on paid hosting unchanged once you put in the new database values.

A full PHP website to start with

If your goal is a real website rather than a test, our PHP blog script with admin panel is a complete, fast blog with no WordPress and no plugins:

  • Articles with a cover picture, reading time, a table of contents and an FAQ section that Google reads as structured data
  • Categories with sub-categories, live search, and editable About, Contact, Privacy and Terms pages
  • SEO built in: canonical links, Open Graph, a sitemap and llms.txt, plus AdSense places
  • A web installer, and admin security with a login lockout after 4 wrong passwords

It needs PHP 8.1 or newer and MySQL, which every normal paid host has. We also have a digital products shop, an online tools website and an HTML5 game portal that install the same way.

Where to go next

Questions people ask

Can I host a PHP website for free?
Yes. Free hosts such as InfinityFree run PHP and MySQL with a free subdomain or your own domain and free SSL. They have daily limits and block PHP mail(), so they suit learning, portfolios and tests, not a business.
What is the best free PHP hosting with MySQL?
InfinityFree is the most complete free shared hosting today: 5 GB of disk, up to 400 MySQL databases, a recent PHP version and free SSL, with no ads on your site. For a whole server, Oracle Cloud's free tier gives you a Linux VPS where you install PHP yourself.
Does GitHub Pages support PHP?
No. GitHub Pages, Netlify and Vercel host static files such as HTML, CSS and JavaScript. They cannot run PHP or a MySQL database, so a PHP site needs PHP hosting.
Why does localhost not work as the database host on free hosting?
On free hosting the database runs on a separate server. Copy the MySQL host name shown in the control panel, such as sql123.infinityfree.com, together with the prefixed database and user names.
How do I send email from a PHP site on free hosting?
PHP's mail() is blocked on free hosts to stop spam. Use an outside mail service over SMTP, for example with PHPMailer on port 587 with TLS.
Is 000webhost still available?
No. 000webhost closed in 2024, so guides that recommend it are out of date. InfinityFree is the usual replacement for free PHP and MySQL hosting.
Can I use my own domain on free hosting?
Yes, InfinityFree lets you add a domain you own by pointing its nameservers to the free host, and it offers free SSL for it. You can also start with a free subdomain.
Which folder do I upload to on InfinityFree?
The htdocs folder of your hosting account, not public_html. Your index.php must be directly inside htdocs.
Is free hosting good for a business website?
No. A site that goes over the daily limits is suspended until the next day, email from the site is blocked, and there is no uptime promise. Use paid hosting once the site has customers.
How do I move from free hosting to paid hosting?
Download your files and export the database from phpMyAdmin, upload both to the new host, and change the database host, name, user and password in your config file. On cPanel hosting the host is usually localhost.

Written by Habib Baloch

I build Android apps, websites and Ubuntu servers, and write down exactly how I did it.

Ask me about this guide →