Mastering the Gemini File API: Upload, Manage, and Prompt With Media Files
A practical guide to the Gemini File API - uploading images, audio, video, and documents up to 2GB, managing file lifecycles, and using them in multimodal prompts with best practices for getting reliable outputs.
Published on • August 5, 2026
AI Assistant

Introduction
Gemini can handle various types of input data — text, images, and audio — at the same time. But to unlock truly multimodal applications, you need a reliable way to get large media files into your prompts. That’s where the Gemini File API comes in.
The File API lets you upload media files, store them temporarily, retrieve metadata, list them, and delete them. The basic operations are identical for audio files, images, videos, documents, and other supported file types. In this post we’ll cover the full file lifecycle — upload, get metadata, list, delete — plus prompt strategies for getting the best results from multimodal input.
When to use the File API
Always use the File API when the total request size (including the files, text prompt, system instructions, etc.) is larger than 100 MB. For PDF files, the limit is 50 MB for inline data. For larger files, the File API handles it for you:
- Store up to 20 GB of files per project.
- Each file can be up to 2 GB.
- Files are stored for 48 hours (you can extend this with Google Cloud Storage registration).
- It’s available at no cost in all regions where the Gemini API is available.
Upload a file
Uploading is straightforward: you give the API a file path and a MIME type, then use the returned uri and mime_type directly in an interaction.
Python
from google import genai
client = genai.Client()
myfile = client.files.upload(file="path/to/sample.mp3")
interaction = client.interactions.create(
model="gemini-3.6-flash",
input=[
{"type": "text", "text": "Describe this audio clip"},
{"type": "audio", "uri": myfile.uri, "mime_type": myfile.mime_type}
]
)
print(interaction.output_text)
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
async function main() {
const myfile = await client.files.upload({
file: "path/to/sample.mp3",
config: { mime_type: "audio/mpeg" },
});
const interaction = await client.interactions.create({
model: "gemini-3.6-flash",
input: [
{ type: "text", text: "Describe this audio clip" },
{ type: "audio", uri: myfile.uri, mime_type: myfile.mimeType }
]
});
console.log(interaction.output_text);
}
await main();
Go
file, err := client.Files.UploadFromPath(ctx, "path/to/sample.mp3", nil)
if err != nil {
log.Fatal(err)
}
defer client.Files.Delete(ctx, file.Name)
interaction, err := client.Interactions.Create(ctx, "gemini-3.6-flash", &genai.InteractionRequest{
Input: []interface{}{
genai.NewPartFromFile(*file),
genai.NewPartFromText("Describe this audio clip"),
},
}, nil)
if err != nil {
log.Fatal(err)
}
// Print the model's text response
for _, step := range interaction.Steps {
if step.Type == "model_output" {
for _, part := range step.Content {
if part.Type == "text" {
fmt.Println(part.Text)
}
}
}
}
REST
AUDIO_PATH="path/to/sample.mp3"
MIME_TYPE=$(file -b --mime-type "${AUDIO_PATH}")
NUM_BYTES=$(wc -c < "${AUDIO_PATH}")
DISPLAY_NAME=AUDIO
tmp_header_file=upload-header.tmp
# Initial resumable request defining metadata.
# The upload url is in the response headers dump them to a file.
curl "${BASE_URL}/upload/v1beta/files" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-D "${tmp_header_file}" \
-H "X-Goog-Upload-Protocol: resumable" \
-H "X-Goog-Upload-Command: start" \
-H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \
-H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \
-H "Content-Type: application/json" \
-d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null
upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r")
rm "${tmp_header_file}"
# Upload the actual bytes.
curl "${upload_url}" \
-H "Content-Length: ${NUM_BYTES}" \
-H "X-Goog-Upload-Offset: 0" \
-H "X-Goog-Upload-Command: upload, finalize" \
--data-binary "@${AUDIO_PATH}" 2> /dev/null > file_info.json
file_uri=$(jq ".file.uri" file_info.json)
echo file_uri=$file_uri
# Now create an interaction using the Interactions API
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"model": "gemini-3.6-flash",
"input": [
{"type": "text", "text": "Describe this audio clip"},
{"type": "audio", "uri": '$file_uri', "mime_type": "'${MIME_TYPE}'"}
]
}' 2> /dev/null > response.json
cat response.json
echo
jq ".outputs[] | select(.type == \"text\") | .text" response.json
Get metadata for a file
You can verify that the API successfully stored the uploaded file and get its metadata by calling files.get.
Python
from google import genai
client = genai.Client()
myfile = client.files.upload(file='path/to/sample.mp3')
file_name = myfile.name
myfile = client.files.get(name=file_name)
print(myfile)
JavaScript
import {
GoogleGenAI,
} from "@google/genai";
const client = new GoogleGenAI({});
async function main() {
const myfile = await client.files.upload({
file: "path/to/sample.mp3",
config: { mime_type: "audio/mpeg" },
});
const fileName = myfile.name;
const fetchedFile = await client.files.get({ name: fileName });
console.log(fetchedFile);
}
await main();
Go
file, err := client.Files.UploadFromPath(ctx, "path/to/sample.mp3", nil)
if err != nil {
log.Fatal(err)
}
gotFile, err := client.Files.Get(ctx, file.Name)
if err != nil {
log.Fatal(err)
}
fmt.Println("Got file:", gotFile.Name)
REST
# file_info.json was created in the upload example
name=$(jq -r ".file.name" file_info.json)
# Get the file of interest to check state
curl https://generativelanguage.googleapis.com/v1beta/$name \
-H "x-goog-api-key: $GEMINI_API_KEY" > file_info.json
# Print some information about the file you got
name=$(jq -r ".name" file_info.json)
echo name=$name
file_uri=$(jq -r ".uri" file_info.json)
echo file_uri=$file_uri
List uploaded files
Need to see everything you’ve uploaded? The following code gets a list of all files.
Python
from google import genai
client = genai.Client()
print('My files:')
for f in client.files.list():
print(' ', f.name)
JavaScript
import {
GoogleGenAI,
} from "@google/genai";
const client = new GoogleGenAI({});
async function main() {
const listResponse = await client.files.list({ config: { pageSize: 10 } });
for await (const file of listResponse) {
console.log(file.name);
}
}
await main();
Go
for file, err := range client.Files.All(ctx) {
if err != nil {
log.Fatal(err)
}
fmt.Println(file.Name)
}
REST
echo "My files: "
curl "https://generativelanguage.googleapis.com/v1beta/files" \
-H "x-goog-api-key: $GEMINI_API_KEY"
Delete uploaded files
Files are automatically deleted after 48 hours. You can also manually delete an uploaded file:
Python
from google import genai
client = genai.Client()
myfile = client.files.upload(file='path/to/sample.mp3')
client.files.delete(name=myfile.name)
JavaScript
import {
GoogleGenAI,
} from "@google/genai";
const client = new GoogleGenAI({});
async function main() {
const myfile = await client.files.upload({
file: "path/to/sample.mp3",
config: { mime_type: "audio/mpeg" },
});
const fileName = myfile.name;
await client.files.delete({ name: fileName });
}
await main();
Go
file, err := client.Files.UploadFromPath(ctx, "path/to/sample.mp3", nil)
if err != nil {
log.Fatal(err)
}
client.Files.Delete(ctx, file.Name)
REST
curl --request "DELETE" https://generativelanguage.googleapis.com/v1beta/$name \
-H "x-goog-api-key: $GEMINI_API_KEY"
Usage info
- Store up to 20 GB of files per project, with a per-file maximum of 2 GB.
- Files are stored for 48 hours.
- During that time you can get metadata about the files, but you can’t download them.
- The File API is free in all regions where the Gemini API is available.
File prompting strategies
Uploading files is only half the battle — you also need to prompt well. Using media in your prompts gives you enormous flexibility. For example, you can send the model a photo of a delicious meal and ask it to write a short blog post about your meal prepping journey.
If you’re having trouble getting the output you want, these strategies help:
Be specific in your instructions
Prompts have the most success when they are clear and detailed. If you need the model to parse a time and a city from an airport board, don’t ask it to just “describe this image” — say exactly what to extract. For example, “Parse the time and city from the airport board shown in this image into a list.” The difference in output quality is dramatic.
Add a few examples (few-shot learning)
The model can use multiple inputs as examples to understand the output you want. If you want the city but not the country, give it examples like colosseum -> city: Rome, landmark: the Colosseum so it follows the same pattern for your new image.
Break it down step-by-step
For complex tasks that require both visual understanding and reasoning, split the task into smaller steps, or ask the model to “think step by step.” For example, when asked “When will I run out of toilet paper?” the model might just say “soon.” But ask it to: 1. count the rolls, 2. estimate daily usage, 3. calculate how long they’ll last and you get a reasoned, reliable answer. Math and word problems are great candidates for this pattern.
Specify the output format
If the output needs to be ingested downstream, tell the model the format: “Parse the table in this image into Markdown format” or “Provide a list of ingredients, type of cuisine, vegetarian or not, in JSON format.” Explicit format instructions remove the guesswork.
Put your image first for single-image prompts
While Gemini can interpret image and text in any order, placing a single image before the text prompt often leads to better results.
Troubleshooting multimodal prompts
Sometimes the model gets it wrong. Here’s how to debug:
- The model ignores the relevant part of the image: Drop hints about which aspects of the image the prompt should draw from.
- The output is too generic: Ask the model to describe the image(s) before performing its reasoning task, or ask it to refer to what’s in the images.
- Not sure which part failed: Ask the model to describe the image, or explain its reasoning — that tells you whether it failed to understand the image or failed at the reasoning step.
- Hallucinated content: Dial down the temperature, or ask for shorter descriptions so the model is less likely to extrapolate.
- Tune sampling parameters: Experiment with temperature and top-k to adjust creativity.
Summary
The Gemini File API is the backbone of multimodal applications. Upload media files up to 2GB, manage them with get/list/delete operations, reference them by URI in any interaction, and combine them with smart prompting strategies to get accurate, well-formatted, reliable outputs. Combined with the Interactions API, it gives you a complete pipeline for building multimodal AI features.
Further reading
- Try writing your own multimodal prompts using Google AI Studio.
- For including files in your prompts, see the Vision, Audio, and Document processing guides.
- For more on prompt design and tuning sampling parameters, see the Prompt strategies page.