To get the public URL of a Firebase Storage file, use getDownloadURL() from the modular SDK with a storage reference. This returns a long-lived HTTPS URL with an access token, making the file accessible to anyone with the link. For truly public URLs without tokens, make the bucket public using Google Cloud IAM. For temporary access, generate signed URLs with the Firebase Admin SDK. Always call getDownloadURL after the upload completes.
Getting the Public URL of a Firebase Storage File
Firebase Storage provides multiple ways to generate URLs for accessing files. The getDownloadURL() method returns a token-based URL that bypasses security rules. For permanent public access, you can set IAM permissions on the bucket. For temporary sharing, signed URLs with expiration times offer the most control. This tutorial covers all three approaches and when to use each.
Prerequisites
- A Firebase project with Cloud Storage enabled
- Firebase JS SDK v9+ installed
- At least one file uploaded to Firebase Storage
- Admin SDK configured for signed URL generation (optional)
Step-by-step guide
Get a download URL with getDownloadURL
Get a download URL with getDownloadURL
The most common method is getDownloadURL(), which returns an HTTPS URL with an embedded access token. This URL bypasses storage security rules — anyone with the URL can access the file, even without authentication. The token is generated when the file is uploaded or when you explicitly request a new one. Import ref and getDownloadURL from firebase/storage.
1import { getStorage, ref, getDownloadURL } from 'firebase/storage';23const storage = getStorage();45async function getFileUrl(filePath: string): Promise<string> {6 const fileRef = ref(storage, filePath);7 const url = await getDownloadURL(fileRef);8 console.log('Download URL:', url);9 return url;10}1112// Example: get URL for an uploaded image13const url = await getFileUrl('users/abc123/avatar.jpg');14// Returns: https://firebasestorage.googleapis.com/v0/b/BUCKET/o/users%2Fabc123%2Favatar.jpg?alt=media&token=TOKENExpected result: A long-lived HTTPS URL is returned that can be used in img tags, fetch calls, or shared directly.
Get the download URL immediately after uploading
Get the download URL immediately after uploading
When uploading a file, chain getDownloadURL after the upload completes to get the URL for the newly uploaded file. This is the standard pattern for displaying uploaded images or providing download links. Use the snapshot reference from uploadBytes or listen for the complete event on uploadBytesResumable.
1import { getStorage, ref, uploadBytes, getDownloadURL } from 'firebase/storage';23const storage = getStorage();45async function uploadAndGetUrl(file: File, path: string): Promise<string> {6 const fileRef = ref(storage, path);78 // Upload the file9 await uploadBytes(fileRef, file);1011 // Get the download URL12 const url = await getDownloadURL(fileRef);13 return url;14}1516// With resumable upload and progress17import { uploadBytesResumable } from 'firebase/storage';1819function uploadWithProgress(file: File, path: string): Promise<string> {20 return new Promise((resolve, reject) => {21 const fileRef = ref(storage, path);22 const task = uploadBytesResumable(fileRef, file);2324 task.on('state_changed',25 (snapshot) => {26 const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;27 console.log(`Upload: ${progress.toFixed(0)}%`);28 },29 reject,30 async () => {31 const url = await getDownloadURL(task.snapshot.ref);32 resolve(url);33 }34 );35 });36}Expected result: The download URL is available immediately after the upload completes and can be stored in Firestore or displayed in the UI.
Store the download URL in Firestore for later use
Store the download URL in Firestore for later use
A common pattern is to store the download URL in a Firestore document right after uploading. This way, you do not need to call getDownloadURL again when displaying the file — just read the URL from Firestore. This is more efficient because Firestore reads are cheaper than Storage API calls at scale.
1import { getStorage, ref, uploadBytes, getDownloadURL } from 'firebase/storage';2import { getFirestore, doc, updateDoc } from 'firebase/firestore';34const storage = getStorage();5const db = getFirestore();67async function uploadUserAvatar(8 userId: string,9 file: File10): Promise<string> {11 // Upload to a user-specific path12 const filePath = `users/${userId}/avatar.jpg`;13 const fileRef = ref(storage, filePath);14 await uploadBytes(fileRef, file);1516 // Get the download URL17 const url = await getDownloadURL(fileRef);1819 // Store the URL in the user's Firestore document20 await updateDoc(doc(db, 'users', userId), {21 avatarUrl: url,22 avatarPath: filePath23 });2425 return url;26}Expected result: The download URL is saved in Firestore alongside the storage path, enabling efficient file display without repeated getDownloadURL calls.
Make files truly public with Google Cloud IAM
Make files truly public with Google Cloud IAM
Download URLs with tokens still require the token in the URL. For truly public files (like public website assets), you can make the bucket or a specific path publicly readable through Google Cloud IAM. Go to the Google Cloud Console > Cloud Storage > Your bucket > Permissions. Add the allUsers principal with the Storage Object Viewer role. This makes every file in the bucket readable via a simple public URL pattern.
1// After setting allUsers as Storage Object Viewer on your bucket,2// files are accessible via this public URL pattern:3// https://storage.googleapis.com/YOUR-BUCKET/path/to/file.jpg45// No token needed — the URL is permanent and public6function getPublicUrl(bucket: string, filePath: string): string {7 const encodedPath = encodeURIComponent(filePath)8 .replace(/%2F/g, '/');9 return `https://storage.googleapis.com/${bucket}/${encodedPath}`;10}1112// Example:13const publicUrl = getPublicUrl(14 'myproject.appspot.com',15 'public/hero-image.jpg'16);Expected result: Files are accessible via a clean public URL without any access token, suitable for CDN caching and public sharing.
Generate time-limited signed URLs with the Admin SDK
Generate time-limited signed URLs with the Admin SDK
For temporary file sharing, use the Firebase Admin SDK (server-side) to generate signed URLs that expire after a specified duration. Signed URLs are ideal for sharing files that should only be accessible for a limited time, like download links in emails or temporary previews.
1// Server-side: Node.js with Firebase Admin SDK2import { initializeApp, cert } from 'firebase-admin/app';3import { getStorage } from 'firebase-admin/storage';45const app = initializeApp({6 credential: cert('./service-account.json'),7 storageBucket: 'YOUR-PROJECT.appspot.com'8});910const bucket = getStorage(app).bucket();1112async function getSignedUrl(13 filePath: string,14 expiresInMinutes: number = 6015): Promise<string> {16 const file = bucket.file(filePath);17 const [url] = await file.getSignedUrl({18 action: 'read',19 expires: Date.now() + expiresInMinutes * 60 * 100020 });21 return url;22}2324// URL expires in 24 hours25const tempUrl = await getSignedUrl('users/abc123/report.pdf', 1440);Expected result: A signed URL is returned that provides read access to the file for the specified duration, after which it returns a 403 error.
Complete working example
1import { initializeApp } from 'firebase/app';2import {3 getStorage,4 ref,5 uploadBytes,6 getDownloadURL7} from 'firebase/storage';8import { getFirestore, doc, updateDoc } from 'firebase/firestore';910const app = initializeApp({11 // Your Firebase config12});13const storage = getStorage(app);14const db = getFirestore(app);1516// Get download URL for an existing file17export async function getFileUrl(filePath: string): Promise<string> {18 return getDownloadURL(ref(storage, filePath));19}2021// Upload file and get URL in one step22export async function uploadAndGetUrl(23 file: File,24 path: string25): Promise<string> {26 const fileRef = ref(storage, path);27 await uploadBytes(fileRef, file);28 return getDownloadURL(fileRef);29}3031// Upload avatar and save URL to Firestore32export async function uploadUserAvatar(33 userId: string,34 file: File35): Promise<string> {36 const path = `users/${userId}/avatar.jpg`;37 const fileRef = ref(storage, path);38 await uploadBytes(fileRef, file);3940 const url = await getDownloadURL(fileRef);41 await updateDoc(doc(db, 'users', userId), {42 avatarUrl: url,43 avatarPath: path44 });4546 return url;47}4849// Construct a public URL (bucket must have allUsers IAM)50export function getPublicUrl(51 bucket: string,52 filePath: string53): string {54 const encoded = encodeURIComponent(filePath).replace(/%2F/g, '/');55 return `https://storage.googleapis.com/${bucket}/${encoded}`;56}Common mistakes when getting the Public URL of a Firebase Storage File
Why it's a problem: Calling getDownloadURL before the upload finishes
How to avoid: Always await the uploadBytes call before calling getDownloadURL. For resumable uploads, get the URL in the complete callback, not before.
Why it's a problem: Assuming download URL tokens expire like signed URLs
How to avoid: Download URL tokens do not expire automatically. They remain valid until the file is deleted or re-uploaded (which generates a new token). If you need expiring URLs, use signed URLs from the Admin SDK.
Why it's a problem: Making the entire storage bucket public when only specific files need public access
How to avoid: Use a separate bucket or folder for public files. Set allUsers IAM only on that specific path, or use download URLs with tokens for authenticated access.
Best practices
- Store download URLs in Firestore after upload to avoid repeated getDownloadURL calls
- Store both the download URL and the storage path — URL for display, path for management
- Use a separate public bucket for truly public assets to avoid accidentally exposing user files
- Generate signed URLs server-side for temporary file sharing with expiration
- Use getDownloadURL for authenticated app features and public IAM URLs for public website assets
- Validate file uploads with security rules before generating download URLs
- Cache download URLs on the client to reduce network requests
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
Show me how to get the public download URL of a Firebase Storage file using the modular SDK v9+. Include examples for getting the URL of an existing file, uploading and getting the URL in one step, storing the URL in Firestore, making files truly public with Google Cloud IAM, and generating time-limited signed URLs with the Admin SDK.
Create Firebase Storage URL utilities: getDownloadURL for existing files, upload-then-get-url workflow, save URL to Firestore alongside storage path, public URL construction for IAM-public buckets, and a server-side signed URL generator using the Admin SDK. Use TypeScript and modular SDK v9+.
Frequently asked questions
Do Firebase Storage download URLs expire?
No. Download URLs generated by getDownloadURL contain a token that does not expire. The URL remains valid until the file is deleted, re-uploaded, or you manually revoke the token in the Firebase Console.
Can anyone access a file using the download URL?
Yes. Download URLs with tokens bypass security rules. Anyone with the URL can download the file, even without a Firebase account. Treat download URLs as semi-public links.
How do I revoke access to a download URL?
You can revoke the token by deleting and re-uploading the file, which generates a new token and invalidates the old URL. There is also a 'Revoke' option in the Firebase Console Storage browser for each file.
What is the difference between getDownloadURL and a signed URL?
getDownloadURL returns a permanent URL with an access token. Signed URLs (generated server-side with the Admin SDK) have a configurable expiration time, after which they stop working.
Can I customize the download URL format?
No. Firebase download URLs follow a fixed format with the token parameter. For clean URLs, use a CDN in front of your storage bucket or configure a custom domain for Cloud Storage.
Can RapidDev help set up a file management system with Firebase Storage?
Yes, RapidDev can build a complete file management system including uploads, URL generation, Firestore metadata storage, access control, and CDN integration for your Firebase project.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation