Spotify for Creators has no public API for episode uploads. The file picker can't be triggered programmatically — browser security blocks it. There's no CLI, no webhook, no endpoint to hit.
So we built one anyway.
This is the field note for the session where we published all 15 Hold the Row episodes to Spotify in a single run — titles, descriptions, and audio files up to 78MB — using nothing but browser automation and a JavaScript pattern that routes around every restriction the platform puts in front of you.
The Chrome MCP tool we use for browser automation has a 10MB limit on file injection. Every Hold the Row audio file is between 30MB and 78MB. Direct upload was off the table.
The native file picker — the one you click to select a file from your computer — can't be opened by JavaScript. That's an intentional browser security boundary. You can't call .click() on a file input and expect a dialog to open.
What you can do is assign a FileList directly to input.files. The browser allows this. Spotify's UI watches for it. So the question becomes: where do you get the file?
The audio files already live on this server at tff365.com/audio/. We added CORS headers to the Caddy config so JavaScript running inside Spotify's browser tab can fetch across origins:
Then, from inside Spotify's tab, for each episode:
The browser fetches the file from tff365.com, builds it into a File object, wraps it in a DataTransfer, and assigns it to Spotify's hidden file input. Spotify thinks a user just picked a file. The upload begins.
No size limit. No manual interaction. Works on every file we threw at it.
Spotify's description field is a rich text editor. If you programmatically type into it or set .value the normal way, you get garbled output — the editor's internal state doesn't sync with what you injected.
The fix: toggle the field into raw HTML mode first (there's a small toggle in the UI), then use the native value setter — the one defined on HTMLTextAreaElement.prototype, not the one the React layer has overridden:
React sees the dispatch, syncs its internal state, and the description is clean on the Review page.
If a platform exposes a UI, you can usually automate it. The file picker isn't the only path into a file input — it's just the one they show you.
Having your assets on infrastructure you control — with headers you can set — means you can use them as a resource from inside any browser tab. tff365.com became the upload source for Spotify.
Most React form fields intercept .value = x and don't fire the right events. Go one level deeper — use the prototype's native setter and dispatch your own events.
This works on any web-based platform that accepts input[type="file"] and doesn't lock down its CSP. YouTube Studio, podcast platforms, CMS file uploaders — same pattern, different URL.