When I rebuilt ramrom.io as plain PHP for shared hosting, I hit a problem that has nothing to do with downloading videos: where do you put an API key on a host that gives you no environment variables, no secrets manager, and no shell?

The downloader talks to RapidAPI, and every request needs the key in a header. If it leaks, someone else burns my quota, and on a free tier that quota is the whole budget. So my rule was simple: the key must never reach the browser, never appear in a file the web server will serve as plain text, and never be typed into anything I might screenshot.

Shared hosting took the usual answers off the table. There is no .env loader and no place to set a server environment variable that survives a restart. So I did what PHP developers have done for twenty years: I put the key in a plain PHP file, and then I made sure nobody can read that file over the web.

The file is api/config.php, and it does almost nothing:

<?php return [ 'rapidapi_key' => 'YOUR_KEY_HERE', ]; 

The code loads it with one line — $config = require __DIR__ . '/config.php'; — and passes the key as a header on the server-side request. The visitor's browser never sees it, because the request to RapidAPI happens in PHP on my server, not in JavaScript on their machine. That is the first win: a key in browser JavaScript is not a secret at all, it is a public announcement. If your front-end code needs a key, the call belongs on the server.

But a PHP file is only safe as long as it stays a PHP file. If the server ever stops executing PHP and starts serving files as text — a misconfigured update, a broken handler — the key would be printed to anyone who asked for the URL. So the file gets a second layer of protection: an .htaccess rule in the same folder that refuses to serve it at all.

<Files "config.php"> Require all denied </Files> 

Now a request for the file returns a 403, whether PHP is working or not. I checked it the way a visitor would: opened the URL in a browser, saw the 403, and I run a quick curl against it after every deploy. That check costs ten seconds — a secret you never test is one you are only guessing about.

A few habits keep the setup honest:

  • One place, one key. Every provider call reads the same file, so rotating a key means editing one line in one file, not hunting through the codebase.
  • Nothing else lives next to it. The api/ folder holds code, not uploads, so no backup zip or uploaded file can land beside the config and get served.
  • The key never appears in error output. If a provider call fails, the visitor sees "the provider is busy". It never includes request headers, and PHP errors stay off the page with display_errors off.
  • Permissions are boring on purpose. The file is readable by the web server user and nobody else — 640, not 777. There is never a reason to make a config file world-writable.
  • No screenshots, no pastes. When I ask for help, I copy the code around the key, never the key itself. The fastest way to leak a secret is to be helpful in a hurry.

This is not a perfect system. If someone gets shell access, the key is theirs — but then the game is already over, and no amount of clever hiding will save it. What this setup does is close the realistic holes: the browser, the web server, and my own carelessness.

If you are building a small tool on shared hosting and you are tempted to paste the key into your JavaScript because it works, take the afternoon to move it server-side instead. One PHP file, one .htaccess rule, one curl check. It is the least glamorous part of the site, and it is the part I would least like to get wrong.