Tutorials / Automate cPanel: Uploads, Databases & C…

Automate cPanel: Uploads, Databases & Cron Jobs with Playwright

Mt
Antony Njagi KigunduCore Mtaalam Technologies

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.

How it works

The whole approach rests on three ideas:

  • Log in once with Playwright, handling the quirks (cpsess token timing, self-signed certs, username formats).
  • Use the session — every authenticated UAPI call reuses the cookies Playwright already holds.
  • Never fight the terminal. cPanel’s embedded xterm.js drops keyboard input in headless mode, so all file writes go through UAPI’s save_file_content instead.

    Step 1 — Install Playwright

    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.

    Step 2 — Log in (the reliable way)

    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)
    

    Step 3 — Write a file without touching File Manager

    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.

    Step 4 — Create a database

    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' })
    

    Step 5 — Add a cron job

    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.

    Common traps (learned the hard way)

  • cpsess token timing: the token in the URL changes on every login. Always parse it after a 3–4 second settle, never from the pre-login URL.
  • Username formats: if plain username fails, retry with username@domain.com.
  • CSF lockouts: repeated failed logins can auto-block your IP. Whitelist your dev IP in WHM → CSF first, especially when testing.
  • Headless xterm: the terminal widget is decorative in headless mode — never rely on it for input.

    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.

    Go further

    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.

  • Clone cPanel Navigator on GitHub ↗
  • Documentation hub
  • Hire us to automate your hosting workflows
  • Keep building

    Want this kind of capability in your business?

    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
    Chat with us