Skip to content
Blog

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