Docs › Uploads from a browser
Uploads from a browser
To let your users upload from your web app without exposing your key, split the work between your backend and the browser:
- The browser tells your backend the file name and size.
- Your backend calls
POST /videosandPOST /videos/{id}/parts, and returns only thevideoId, thepartSizeand the part URLs. - The browser
PUTs each slice (file.slice(start, start + sizeBytes)) straight to its URL. Storage accepts cross-originPUTs, and exposes theETagheader. - The browser tells your backend it's done; your backend calls
complete.
// Browser: upload the slices your backend signed
for (const part of parts) {
const start = (part.partNumber - 1) * partSize;
const response = await fetch(part.url, { method: "PUT", body: file.slice(start, start + part.sizeBytes) });
if (!response.ok) throw new Error(`Part ${part.partNumber} failed`);
}
For playback in the browser, pass the status's playbackUrl or streamUrl to the page (see Build your own player); for downloads, the downloadUrl, which is valid for 15 minutes.
Warm-up for faster processing
Request parts progressively as you upload (e.g., every few parts) rather than requesting all parts at once from the beginning. When you request the last few parts (within 192 MiB from the end of the file), the API automatically starts the processing container early so it boots while those final parts upload. This can cut total processing time nearly in half.
This happens automatically—no extra API calls needed. Asking for all parts at once, starting from part 1, skips warm-up (unless the whole file is ≤192 MiB). The web UI and example code already request parts progressively, so you get this benefit by default.