Tutorials / Automate cPanel: Uploads, Databases & C…
Most developers hate clicking through cPanel — we said it out loud and then did something about it. This tutorial is the practical core of cPanel Navigator, our open-source skill that teaches AI agents to do cPanel and WHM chores: file uploads, database creation, PHP version changes, cron jobs, DNS records and firewall rules.
The headline trick: you do not need to click the File Manager UI at all. cPanel exposes a JSON API (UAPI) — and you can call it directly from inside a Playwright page, bypassing the notoriously flaky web interface.
The whole approach rests on three ideas:
save_file_content instead.
pip install playwright
python -m playwright install chromium
If you prefer the browser-use CLI, the skill supports that path too — this tutorial uses plain Playwright for precision.
cPanel’s login flow has three traps: the session token (cpsessNNN) appears in the URL only after the page settles, some hosts want username@domain instead of a plain username, and the TLS certificate may be self-signed. Here is a login that survives all three:
from playwright.sync_api import sync_playwright
import time
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
ctx = browser.new_context(ignore_https_errors=True)
page = ctx.new_page()
page.goto("https://YOUR_HOST:2083", wait_until="networkidle")
# cpsess token can lag a few seconds after networkidle
time.sleep(4)
page.fill("input[name='user']", "USERNAME")
page.fill("input[name='pass']", "PASSWORD")
page.click("#login_submit")
page.wait_for_load_state("networkidle")
time.sleep(4) # let the cpsess token appear in the URL
print("Logged in:", page.url)
This is the trick that makes everything reliable. UAPI’s Fileman::save_file_content runs inside the authenticated page, so no clicking through folders:
result = page.evaluate("""async () => {
const resp = await fetch('/execute/Fileman/save_file_content', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
dir: '/home/USERNAME/public_html/myapp',
file: 'config.php',
content: '',
})
});
return await resp.json();
}""")
print(result) # {"status": 1, ...} means success
Because this runs fetch from the logged-in page, cPanel treats it as a first-class API call — no WebSocket terminal, no headless keyboard problems, no File Manager drag-and-drop.
Databases are two calls: create the DB, then attach a user with privileges. cPanel usually prefixes both with your username:
# 1. Create database: myapp_db
await call('/execute/Mysql/create_database', { name: 'myapp_db' })
# 2. Add user to DB with ALL privileges
await call('/execute/Mysql/set_privileges_on_database',
{ user: 'myapp_user', database: 'myapp_db', privileges: 'ALL PRIVILEGES' })
await call('/execute/Cron/add_line', {
command: 'php /home/USERNAME/public_html/bot.php > /dev/null 2>&1',
minute: '*/5', hour: '*', day: '*', month: '*', weekday: '*',
})
Now bot.php runs every 5 minutes, and the agent never had to find the Cron Jobs screen.
username@domain.com.Never hardcode credentials in scripts or prompts you share publicly. Pass them at runtime or via environment variables. The cPanel Navigator repo contains no credentials — keep it that way in yours.
The full open-source skill adds WHM coverage (firewall, EasyApache, service restarts), a URL map of 30+ cPanel sections across both Jupiter and Paper Lantern themes, and the browser-use CLI path for agents that prefer natural-language navigation.
Tell us what you are trying to run — we will tell you the honest way to run it. Free consultation, no obligation.
Talk to the team