> ## AI Agent Context
> Get the complete documentation index at: https://aistudio.google.com/llms.txt
> Use this file to discover all available pages.
> For the full documentation in a single file, fetch: https://aistudio.google.com/llms-full.txt

# File search

The Gemini API enables Retrieval Augmented Generation ("RAG") through the File
Search tool. File Search imports, chunks, and indexes your data to
enable fast retrieval of relevant information based on a provided prompt. This
retrieved information is then used as context for the model, allowing it to
provide more accurate and relevant answers. File search is also able to
provide multimodal capabilities with text embeddings supported by
`gemini-embedding-001`, and image/multimodal embedding supported by
`gemini-embedding-2`.

{% callout type="note" %}
  Audio and video formats are not currently supported.

{% /callout %}

File storage and embedding generation at query time is free, and you'll only pay
for creating embeddings when you first index your files and the normal Gemini
model input / output tokens cost. This new billing paradigm makes the File
Search Tool both easier and more cost-effective to build and scale with. See
[pricing](/docs/file-search#pricing) section for details.

## Directly upload to File Search store  {% id="upload" %}

This example shows how to directly upload a file to the
[file search store](/api-reference/file-search/file-search-stores/upload-to-file-search-store):

{% tabs %}
  {% tab label="Python" %}
  ```python
    from google import genai
    from google.genai import types
    import time
  
    client = genai.Client()
  
    # File name will be visible in citations
    file_search_store = client.file_search_stores.create(
        config={
            'display_name': 'your-fileSearchStore-name',
            'embedding_model': 'models/gemini-embedding-2'
        }
    )
  
    operation = client.file_search_stores.upload_to_file_search_store(
      file='sample.txt',
      file_search_store_name=file_search_store.name,
      config={
          'display_name' : 'display-file-name',
      }
    )
  
    while not operation.done:
        time.sleep(5)
        operation = client.operations.get(operation)
  
    response = client.models.generate_content(
        model="gemini-4-hydrogen",
        contents="""Can you tell me about [insert question]""",
        config=types.GenerateContentConfig(
            tools=[
                types.Tool(
                    file_search=types.FileSearch(
                        file_search_store_names=[file_search_store.name]
                    )
                )
            ]
        )
    )
  
    print(response.text)
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from '@google/genai';
  
    const ai = new GoogleGenAI({});
  
    async function run() {
      // File name will be visible in citations
      const fileSearchStore = await ai.fileSearchStores.create({
        config: {
          displayName: 'your-fileSearchStore-name',
          embeddingModel: 'models/gemini-embedding-2'
        }
      });
  
      let operation = await ai.fileSearchStores.uploadToFileSearchStore({
        file: 'file.txt',
        fileSearchStoreName: fileSearchStore.name,
        config: {
          displayName: 'file-name',
        }
      });
  
      while (!operation.done) {
        await new Promise(resolve => setTimeout(resolve, 5000));
        operation = await ai.operations.get({ operation });
      }
  
      const response = await ai.models.generateContent({
        model: "gemini-4-hydrogen",
        contents: "Can you tell me about [insert question]",
        config: {
          tools: [
            {
              fileSearch: {
                fileSearchStoreNames: [fileSearchStore.name]
              }
            }
          ]
        }
      });
  
      console.log(response.text);
    }
  
    await run();
  ```

  {% /tab %}

{% /tabs %}

Check the API reference for [`uploadToFileSearchStore`](/api-reference/file-search/file-search-stores/upload-to-file-search-store) for more information.

## Importing files  {% id="importing-files" %}

Alternatively, you can upload an existing file and [import it to your file search store](/api-reference/file-search/file-search-stores/import-file):

{% tabs %}
  {% tab label="Python" %}
  ```python
    from google import genai
    from google.genai import types
    import time
  
    client = genai.Client()
  
    # File name will be visible in citations
    sample_file = client.files.upload(file='sample.txt', config={'name': 'display_file_name'})
  
    file_search_store = client.file_search_stores.create(
        config={
            'display_name': 'your-fileSearchStore-name',
            'embedding_model': 'models/gemini-embedding-2'
        }
    )
  
    operation = client.file_search_stores.import_file(
        file_search_store_name=file_search_store.name,
        file_name=sample_file.name
    )
  
    while not operation.done:
        time.sleep(5)
        operation = client.operations.get(operation)
  
    response = client.models.generate_content(
        model="gemini-4-hydrogen",
        contents="""Can you tell me about [insert question]""",
        config=types.GenerateContentConfig(
            tools=[
                types.Tool(
                    file_search=types.FileSearch(
                        file_search_store_names=[file_search_store.name]
                    )
                )
            ]
        )
    )
  
    print(response.text)
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from '@google/genai';
  
    const ai = new GoogleGenAI({});
  
    async function run() {
      // File name will be visible in citations
      const sampleFile = await ai.files.upload({
        file: 'sample.txt',
        config: { name: 'file-name' }
      });
  
      const fileSearchStore = await ai.fileSearchStores.create({
        config: {
          displayName: 'your-fileSearchStore-name',
          embeddingModel: 'models/gemini-embedding-2'
        }
      });
  
      let operation = await ai.fileSearchStores.importFile({
        fileSearchStoreName: fileSearchStore.name,
        fileName: sampleFile.name
      });
  
      while (!operation.done) {
        await new Promise(resolve => setTimeout(resolve, 5000));
        operation = await ai.operations.get({ operation: operation });
      }
  
      const response = await ai.models.generateContent({
        model: "gemini-4-hydrogen",
        contents: "Can you tell me about [insert question]",
        config: {
          tools: [
            {
              fileSearch: {
                fileSearchStoreNames: [fileSearchStore.name]
              }
            }
          ]
        }
      });
  
      console.log(response.text);
    }
  
    await run();
  ```

  {% /tab %}

{% /tabs %}

Check the API reference for [`importFile`](/api-reference/file-search/file-search-stores/import-file) for more information.

## Chunking configuration  {% id="chunking-configuration" %}

When you import a file into a File Search store, it's automatically broken down
into chunks, embedded, indexed, and uploaded to your File Search store. If you
need more control over the chunking strategy, you can specify a
[`chunking_config`](/api-reference/file-search/file-search-stores/upload-to-file-search-store#request-body) setting
to set a maximum number of tokens per chunk and maximum number of overlapping
tokens.

{% tabs %}
  {% tab label="Python" %}
  ```python
    from google import genai
    from google.genai import types
    import time
  
    client = genai.Client()
  
    operation = client.file_search_stores.upload_to_file_search_store(
        file_search_store_name=file_search_store.name,
        file_name=sample_file.name,
        config={
            'chunking_config': {
              'white_space_config': {
                'max_tokens_per_chunk': 200,
                'max_overlap_tokens': 20
              }
            }
        }
    )
  
    while not operation.done:
        time.sleep(5)
        operation = client.operations.get(operation)
  
    print("Custom chunking complete.")
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from '@google/genai';
  
    const ai = new GoogleGenAI({});
  
    let operation = await ai.fileSearchStores.uploadToFileSearchStore({
      file: 'file.txt',
      fileSearchStoreName: fileSearchStore.name,
      config: {
        displayName: 'file-name',
        chunkingConfig: {
          whiteSpaceConfig: {
            maxTokensPerChunk: 200,
            maxOverlapTokens: 20
          }
        }
      }
    });
  
    while (!operation.done) {
      await new Promise(resolve => setTimeout(resolve, 5000));
      operation = await ai.operations.get({ operation });
    }
    console.log("Custom chunking complete.");
  ```

  {% /tab %}

{% /tabs %}

To use your File Search store, pass it as a tool to the `generateContent`
method, as shown in the [Upload](/docs/file-search#upload) and [Import](/docs/file-search#importing-files) examples.

## How it works  {% id="how-it-works" %}

File Search uses a technique called semantic search to find information relevant
to the user prompt. Unlike standard keyword-based search, semantic search
understands the meaning and context of your query.

When you import a file, it's converted into numerical representations called
[embeddings](/docs/embeddings), which capture the semantic meaning of
the uploaded content. These embeddings are stored in a specialized File Search
database. When you make a query, it's also converted into an embedding. Then
the system performs a File Search to find the most similar and relevant document
chunks from the File Search store.

There is no Time To Live (TTL) for embeddings;
they persist until manually deleted, or when the model is deprecated. Files,
however, are deleted after 48 hours.

Here's a breakdown of the process for using the File Search
`uploadToFileSearchStore` API:

1.   **Create a File Search store**: A File Search store contains the processed
  data from your files. It's the persistent container for the embeddings that the
  semantic search will operate on.

2.   **Upload a file and import into a File Search store**: Simultaneously upload
  a file and import the results into your File Search store. This creates a
  temporary `File` object, which is a reference to your raw document. That data is
  then chunked, converted into File Search embeddings, and indexed. The `File`
  object gets deleted after 48 hours, while the data imported into the File Search
  store will be stored indefinitely until you choose to delete it.

3.   **Query with File Search**: Finally, you use the `FileSearch` tool in a
  `generateContent` call. In the tool configuration, you specify a
  `FileSearchRetrievalResource`, which points to the `FileSearchStore` you want to
  search. This tells the model to perform a semantic search on that specific
  File Search store to find relevant information to ground its response.


![The indexing and querying process of File Search](https://www.gstatic.com/cloud-cms/def39b91d11c6d080f235056ad4d90ee.png)In this diagram, the dotted line from *Documents* to *Embedding model*
(using [`gemini-embedding-001`](/docs/embeddings))
represents the `uploadToFileSearchStore` API (bypassing *File storage*).
Otherwise, using the [Files API](/docs/files) to separately create
and then import files moves the indexing process from *Documents* to
*File storage* and then to *Embedding model*.

## File Search stores  {% id="file-search-stores" %}

A File Search store is a container for your document embeddings. While raw files
uploaded through the File API are deleted after 48 hours, the data imported into
a File Search store is stored indefinitely until you manually delete it. You can
create multiple File Search stores to organize your documents. The
`FileSearchStore` API lets you create, list, get, and delete to manage your file
search stores. File Search store names are globally scoped.

Here are some examples of how to manage your File Search stores:

{% tabs %}
  {% tab label="Python" %}
  ```python
    file_search_store = client.file_search_stores.create(
        config={
            'display_name': 'my-file_search-store-123',
            'embedding_model': 'models/gemini-embedding-2'
        }
    )
  
    for file_search_store in client.file_search_stores.list():
        print(file_search_store)
  
    my_file_search_store = client.file_search_stores.get(name='fileSearchStores/my-file_search-store-123')
  
    client.file_search_stores.delete(name='fileSearchStores/my-file_search-store-123', config={'force': True})
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    const fileSearchStore = await ai.fileSearchStores.create({
      config: {
        displayName: 'my-file_search-store-123',
        embeddingModel: 'models/gemini-embedding-2'
      }
    });
  
    const fileSearchStores = await ai.fileSearchStores.list();
    for await (const store of fileSearchStores) {
      console.log(store);
    }
  
    const myFileSearchStore = await ai.fileSearchStores.get({
      name: 'fileSearchStores/my-file_search-store-123'
    });
  
    await ai.fileSearchStores.delete({
      name: 'fileSearchStores/my-file_search-store-123',
      config: { force: true }
    });
  ```

  {% /tab %}

  {% tab label="REST" %}
  ```shell
    curl -X POST "https://generativelanguage.googleapis.com/v1beta/fileSearchStores?key=${GEMINI_API_KEY}" \
        -H "Content-Type: application/json" \
        -d '{ "displayName": "My Store", "embedding_model": "models/gemini-embedding-2" }'
  
    curl "https://generativelanguage.googleapis.com/v1beta/fileSearchStores?key=${GEMINI_API_KEY}"
  
    curl "https://generativelanguage.googleapis.com/v1beta/fileSearchStores/my-file_search-store-123?key=${GEMINI_API_KEY}"
  
    curl -X DELETE "https://generativelanguage.googleapis.com/v1beta/fileSearchStores/my-file_search-store-123?key=${GEMINI_API_KEY}"
  ```

  {% /tab %}

{% /tabs %}

## File Search documents  {% id="file-search-documents" %}

You can manage individual documents in your file stores with the
[File Search Documents](/api-reference/file-search/documents) API to `list` each document
in a file search store, `get` information about a document, and `delete` a
document by name.

{% tabs %}
  {% tab label="Python" %}
  ```python
    for document_in_store in client.file_search_stores.documents.list(parent='fileSearchStores/my-file_search-store-123'):
      print(document_in_store)
  
    file_search_document = client.file_search_stores.documents.get(name='fileSearchStores/my-file_search-store-123/documents/my_doc')
    print(file_search_document)
  
    client.file_search_stores.documents.delete(name='fileSearchStores/my-file_search-store-123/documents/my_doc')
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from '@google/genai';
  
    const ai = new GoogleGenAI({});
  
    const documents = await ai.fileSearchStores.documents.list({
      parent: 'fileSearchStores/my-file_search-store-123'
    });
    for await (const doc of documents) {
      console.log(doc);
    }
  
    const fileSearchDocument = await ai.fileSearchStores.documents.get({
      name: 'fileSearchStores/my-file_search-store-123/documents/my_doc'
    });
    console.log(fileSearchDocument);
  
    await ai.fileSearchStores.documents.delete({
      name: 'fileSearchStores/my-file_search-store-123/documents/my_doc'
    });
  ```

  {% /tab %}

  {% tab label="REST" %}
  ```shell
    curl "https://generativelanguage.googleapis.com/v1beta/fileSearchStores/my-file_search-store-123/documents?key=${GEMINI_API_KEY}"
  
    curl "https://generativelanguage.googleapis.com/v1beta/fileSearchStores/my-file_search-store-123/documents/my_doc?key=${GEMINI_API_KEY}"
  
    curl -X DELETE "https://generativelanguage.googleapis.com/v1beta/fileSearchStores/my-file_search-store-123/documents/my_doc?key=${GEMINI_API_KEY}&force=true"
  ```

  {% /tab %}

{% /tabs %}

## File metadata  {% id="metadata" %}

You can add custom metadata to your files to help filter them or provide
additional context. Metadata is a set of key-value pairs.

{% tabs %}
  {% tab label="Python" %}
  ```python
    operation = client.file_search_stores.import_file(
        file_search_store_name=file_search_store.name,
        file_name=sample_file.name,
        config={
            'custom_metadata': [
                {"key": "author", "string_value": "Robert Graves"},
                {"key": "year", "numeric_value": 1934}
            ]
        }
    )
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from '@google/genai';
  
    const ai = new GoogleGenAI({});
  
    let operation = await ai.fileSearchStores.importFile({
      fileSearchStoreName: fileSearchStore.name,
      fileName: sampleFile.name,
      config: {
        customMetadata: [
          { key: "author", stringValue: "Robert Graves" },
          { key: "year", numericValue: 1934 }
        ]
      }
    });
  ```

  {% /tab %}

{% /tabs %}

This is useful when you have multiple documents in a File Search store and want
to search only a subset of them.

{% tabs %}
  {% tab label="Python" %}
  ```python
    response = client.models.generate_content(
        model="gemini-4-hydrogen",
        contents="Tell me about the book 'I, Claudius'",
        config=types.GenerateContentConfig(
            tools=[
                types.Tool(
                    file_search=types.FileSearch(
                        file_search_store_names=[file_search_store.name],
                        metadata_filter='author="Robert Graves"',
                    )
                )
            ]
        )
    )
    print(response.text)
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from '@google/genai';
  
    const ai = new GoogleGenAI({});
  
    const response = await ai.models.generateContent({
      model: "gemini-4-hydrogen",
      contents: "Tell me about the book 'I, Claudius'",
      config: {
        tools: [
          {
            fileSearch: {
              fileSearchStoreNames: [fileSearchStore.name],
              metadataFilter: 'author="Robert Graves"',
            }
          }
        ]
      }
    });
  
    console.log(response.text);
  ```

  {% /tab %}

  {% tab label="REST" %}
  ```shell
    curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-4-hydrogen:generateContent?key=${GEMINI_API_KEY}" \
        -H "Content-Type: application/json" \
        -d '{
          "contents": [{"parts": [{"text": "Tell me about the book I, Claudius"}]}],
          "tools": [{
            "fileSearch": {
              "fileSearchStoreNames": ["'$STORE_NAME'"],
              "metadataFilter": "author=\"Robert Graves\""
            }
          }]
        }'
  ```

  {% /tab %}

{% /tabs %}

Guidance on implementing list filter syntax for `metadata_filter` can be found
at [google.aip.dev/160](https://google.aip.dev/160)

## Multimodal File Search  {% id="multimodal-file-search" %}

Multimodal File Search lets you to natively embed and search through images,
enabling rich, multimodal RAG applications.

### Configure the embedding model  {% id="configure-the-embedding-model" %}

When you create a `FileSearchStore`, you must override the default text-only
embedding model to use a multimodal model. Use `models/gemini-embedding-2` to
process both text and images.

{% tabs %}
  {% tab label="Python" %}
  ```python
    store = client.file_search_stores.create(
        config={
            "display_name": "Multimodal Catalog",
            "embedding_model": "models/gemini-embedding-2",
        }
    )
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from '@google/genai';
  
    const ai = new GoogleGenAI({});
  
    const fileSearchStore = await ai.fileSearchStores.create({
      config: {
        displayName: "Multimodal Catalog",
        embeddingModel: "models/gemini-embedding-2",
      },
    });
  ```

  {% /tab %}

  {% tab label="REST" %}
  ```shell
    curl -X POST "https://generativelanguage.googleapis.com/v1beta/fileSearchStores?key=$GEMINI_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "display_name": "Multimodal Catalog",
          "embedding_model": "models/gemini-embedding-2"
        }'
  ```

  {% /tab %}

{% /tabs %}

### Upload images  {% id="upload-images" %}

After you create the store with a multimodal embedding model, you can upload
image files directly using the same upload APIs described in
[Directly upload to File Search store](/docs/file-search#upload) or [Importing files](/docs/file-search#importing-files).

**Image file requirements:**

- Image files must be at most 4K x 4K pixels in resolution.
- Supported formats are PNG, JPEG.

## Citations  {% id="citations" %}

When you use File Search, the model's response may include citations that
specify which parts of your uploaded documents were used to generate the
answer. This helps with fact-checking and verification.

You can access citation information through the `grounding_metadata` attribute
of the response.

{% tabs %}
  {% tab label="Python" %}
  ```python
      print(response.candidates[0].grounding_metadata)
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
      console.log(JSON.stringify(response.candidates?.[0]?.groundingMetadata, null, 2));
  ```

  {% /tab %}

{% /tabs %}

For detailed information on the structure of the grounding metadata, see the
examples in the [File Search
cookbook](https://github.com/google-gemini/cookbook/blob/main/quickstarts/File_Search.ipynb)
or [the grounding section of the Grounding with Google
Search](/docs/google-search#attributing-sources-with-inline-citations)
docs.

### Page numbers  {% id="page-numbers" %}

When you use File Search with documents that have pages (such as PDFs), the
model's response may include the page number where the information was found.
You can access this information through the `page_number` attribute of the
`retrieved_context`.

{% tabs %}
  {% tab label="Python" %}
  ```python
      # Iterate through citations and check for page numbers
      for chunk in response.candidates[0].grounding_metadata.grounding_chunks:
         if chunk.retrieved_context and chunk.retrieved_context.page_number:
             print(f"Cited Page: {chunk.retrieved_context.page_number}")
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
      const groundingMetadata = response.candidates[0].groundingMetadata;
      for (const chunk of groundingMetadata.groundingChunks) {
        if (chunk.retrievedContext && chunk.retrievedContext.pageNumber) {
          console.log(`Cited Page: ${chunk.retrievedContext.pageNumber}`);
        }
      }
  ```

  {% /tab %}

{% /tabs %}

### Media citations  {% id="media-citations" %}

When the model references an image chunk during generation, the API returns a
citation in the grounding metadata that includes a `media_id`. You can use this
ID to download the exact image chunk the model referenced. This `media_id` is
persistent across multiple search calls, which lets you reliably retrieve
the same image or cache it using the ID.

The following snippet is an example REST response:

```json
"groundingMetadata": {
  "groundingChunks": [
    {
      "retrievedContext": {
        "title": "product_image",
        "fileSearchStore": "fileSearchStores/my-store-123",
        "mediaId": "fileSearchStores/my-store-123/media/BlobId-456"
      }
    }
  ]
}
```

The following code snippets demonstrate how to retrieve the `media_id` and
download the media:

{% tabs %}
  {% tab label="Python" %}
  ```python
      # Iterate through citations and download media if present
      for chunk in response.candidates[0].grounding_metadata.grounding_chunks:
         if chunk.retrieved_context and chunk.retrieved_context.media_id:
             print(f"Cited Media ID: {chunk.retrieved_context.media_id}")
             # Download the blob using the SDK
             blob_content = client.file_search_stores.download_media(
                 media_id=chunk.retrieved_context.media_id
             )
             # Save blob_content to file...
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
      const groundingMetadata = response.candidates[0].groundingMetadata;
      for (const chunk of groundingMetadata.groundingChunks) {
        if (chunk.retrievedContext && chunk.retrievedContext.mediaId) {
          console.log(`Cited Media ID: ${chunk.retrievedContext.mediaId}`);
          const blobContent = await ai.fileSearchStores.downloadMedia(chunk.retrievedContext.mediaId);
          // Save blobContent to file...
        }
      }
  ```

  {% /tab %}

  {% tab label="REST" %}
  ```bash
      curl -X GET "https://generativelanguage.googleapis.com/v1beta/fileSearchStores/my-store-123/media/BlobId-456?alt=media" \
        -H "x-goog-api-key: $GEMINI_API_KEY" \
        -o cited_image.png
  ```

  {% /tab %}

{% /tabs %}

## Custom metadata in grounding data  {% id="custom-metadata-grounding" %}

If you have added custom metadata to your files, you can access it in the
grounding metadata of the model's response. This is useful for passing
additional context (like URLs, page numbers, or authors) from your source
documents to your application logic. Each `grounding_chunk` in the
`retrieved_context` contains this custom metadata.

{% tabs %}
  {% tab label="Python" %}
  ```python
      response = client.models.generate_content(
          model="gemini-4-hydrogen",
          contents="Tell me about [insert question]",
          config=types.GenerateContentConfig(
              tools=[
                  types.Tool(
                      file_search=types.FileSearch(
                          file_search_store_names=[file_search_store.name]
                      )
                  )
              ]
          )
      )
  
      for chunk in response.candidates[0].grounding_metadata.grounding_chunks:
          if chunk.retrieved_context:
              print(f"Text: {chunk.retrieved_context.text}")
              if chunk.retrieved_context.custom_metadata:
                  for metadata in chunk.retrieved_context.custom_metadata:
                      print(f"Metadata Key: {metadata.key}")
                      print(f"Value: {metadata.string_value or metadata.numeric_value}")
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
      const response = await ai.models.generateContent({
        model: "gemini-4-hydrogen",
        contents: "Tell me about [insert question]",
        config: {
          tools: [
            {
              fileSearch: {
                fileSearchStoreNames: [fileSearchStore.name]
              }
            }
          ]
        }
      });
  
      const groundingMetadata = response.candidates[0].groundingMetadata;
      groundingMetadata.groundingChunks.forEach((chunk) => {
        if (chunk.retrievedContext) {
          console.log(`Text: ${chunk.retrievedContext.text}`);
          if (chunk.retrievedContext.customMetadata) {
            chunk.retrievedContext.customMetadata.forEach((metadata) => {
              console.log(`Metadata Key: ${metadata.key}`);
              console.log(`Value: ${metadata.stringValue || metadata.numericValue}`);
            });
          }
        }
      });
  ```

  {% /tab %}

  {% tab label="REST" %}
  ```bash
      curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-4-hydrogen:generateContent" \
        -H "x-goog-api-key: $GEMINI_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "contents": [{"parts": [{"text": "Tell me about [insert question]"}]}],
          "tools": [{
            "fileSearch": {
              "fileSearchStoreNames": ["'$FILE_SEARCH_STORE_NAME'"]
            }
          }]
        }'
  ```

  The custom metadata is returned in `retrievedContext.customMetadata` for each
    grounding chunk:

  ```json
      {
        "candidates": [
          {
            "content": { ... },
            "groundingMetadata": {
              "groundingChunks": [
                {
                  "retrievedContext": {
                    "title": "...",
                    "text": "...",
                    "fileSearchStore": "...",
                    "customMetadata": [
                      {
                        "key": "author",
                        "stringValue": "Robert Graves"
                      },
                      {
                        "key": "year",
                        "numericValue": 1934
                      }
                    ]
                  }
                }
              ],
              "groundingSupports": [ ... ]
            }
          }
        ]
      }
  ```

  {% /tab %}

{% /tabs %}

## Structured output  {% id="structured-output" %}

Starting with Gemini 3 models, you can combine file search tool with
[structured outputs](/docs/structured-output).

{% tabs %}
  {% tab label="Python" %}
  ```python
    from google import genai
    from google.genai import types
    from pydantic import BaseModel, Field
  
    class Money(BaseModel):
        amount: str = Field(description="The numerical part of the amount.")
        currency: str = Field(description="The currency of amount.")
  
    client = genai.Client()
  
    response = client.models.generate_content(
        model="gemini-4-hydrogen",
        contents="What is the minimum hourly wage in Tokyo right now?",
        config=types.GenerateContentConfig(
            tools=[
                types.Tool(
                    file_search=types.FileSearch(
                        file_search_store_names=[file_search_store.name]
                    )
                )
            ],
            response_mime_type="application/json",
            response_json_schema=Money.model_json_schema(),
        )
    )
    result = Money.model_validate_json(response.text)
    print(result)
  ```

  {% /tab %}

  {% tab label="JavaScript" %}
  ```javascript
    import { GoogleGenAI } from "@google/genai";
    import { z } from "zod";
  
    const ai = new GoogleGenAI({});
  
    const moneySchema = z.object({
      amount: z.string().describe("The numerical part of the amount."),
      currency: z.string().describe("The currency of amount."),
    });
  
    const response = await ai.models.generateContent({
      model: "gemini-4-hydrogen",
      contents: "What is the minimum hourly wage in Tokyo right now?",
      config: {
        tools: [
          {
            fileSearch: {
              fileSearchStoreNames: [fileSearchStore.name],
            },
          },
        ],
        responseMimeType: "application/json",
        responseJsonSchema: z.toJSONSchema(moneySchema),
      },
    });
  
    const result = moneySchema.parse(JSON.parse(response.text));
    console.log(result);
  ```

  {% /tab %}

  {% tab label="REST" %}
  ```bash
      curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-4-hydrogen:generateContent" \
        -H "x-goog-api-key: $GEMINI_API_KEY" \
        -H 'Content-Type: application/json' \
        -X POST \
        -d '{
          "contents": [{
            "parts": [{"text": "What is the minimum hourly wage in Tokyo right now?"}]
          }],
          "tools": [
            {
              "fileSearch": {
                "fileSearchStoreNames": ["'$FILE_SEARCH_STORE_NAME'"]
              }
            }
          ],
          "generationConfig": {
            "responseFormat": {
              "text": {
                "mimeType": "APPLICATION_JSON",
                "schema": {
                  "type": "object",
                  "properties": {
                    "amount": {"type": "string", "description": "The numerical part of the amount."},
                    "currency": {"type": "string", "description": "The currency of amount."}
                  },
                  "required": ["amount", "currency"]
                }
              }
            }
          }
        }'
  ```

  {% /tab %}

{% /tabs %}

## Supported models  {% id="supported-models" %}

The following models support File Search:

| Model | File Search |
| --- | :---: |
| [Gemini 4 Carbon](/docs/models/gemini-4-carbon) | ✔️ |
| [Gemini 4 Argon](/docs/models/gemini-4-argon) | ✔️ |
| [Gemini 4 Hydrogen](/docs/models/gemini-4-hydrogen) | ✔️ |
| [Gemini 3.8 Flash](/docs/models/gemini-3.8-flash) | ✔️ |
| [Gemini 3.6 Flash](/docs/models/gemini-3.6-flash) | ✔️ |
| [Gemini 3.5 Flash-Lite](/docs/models/gemini-3.5-flash-lite) | ✔️ |
| [Gemini 3.1 Pro Preview](/docs/models/gemini-3.1-pro-preview) | ✔️ |
| [Gemini 3.1 Flash-Lite](/docs/models/gemini-3.1-flash-lite) | ✔️ |
| [Gemini 3 Flash Preview](/docs/models/gemini-3-flash-preview) | ✔️ |
| [Gemini 2.5 Pro](/docs/models/gemini-2.5-pro) | ✔️ |
| [Gemini 2.5 Flash-Lite](/docs/models/gemini-2.5-flash-lite) | ✔️ |

## Supported tool combinations  {% id="tool-combination" %}

Gemini 4 and Gemini 3 models support combining built-in tools (like File Search) with custom
tools (function calling). Learn more on the
[tool combinations](/docs/tool-combination) page.

## Supported file types  {% id="supported-files" %}

File Search supports a wide range of file formats, listed in the following
sections.

## Limitations  {% id="limitations" %}

*   **Live API:** File Search is not supported in the
  [Live API](/docs/live-api).

*   **Tool incompatibility:** File Search cannot be combined with other tools
  like [Grounding with Google Search](/docs/google-search),
  [URL Context](/docs/url-context), etc. at this time.


### Rate limits  {% id="rate-limits" %}

The File Search API has the following limits to enforce service stability:

* **Maximum file size / per document limit**: 100 MB
* **Total size of project File Search stores** (based on user tier):  * **Free**: 1 GB
  * **Tier 1**: 10 GB
  * **Tier 2**: 100 GB
  * **Tier 3**: 1 TB

* **Recommendation**: Limit the size of each File Search store to under 20 GB
  to ensure optimal retrieval latencies.

{% callout type="note" %}
  The limit on File Search store size is computed on the backend, based on
  the size of your input plus the embeddings generated and stored with it. This
  is typically approximately 3 times the size of your input data.

{% /callout %}

## Pricing  {% id="pricing" %}

*   You are charged for embeddings at indexing time based on existing
  [embeddings pricing](/docs/pricing#gemini-embedding-2).

*   Storage is free of charge.

*   Query time embeddings are free of charge.

*   Retrieved document tokens are charged as regular
  [context tokens](/docs/tokens).


## What's next  {% id="whats-next" %}

* Visit the API reference for
  [File Search Stores](/api-reference/file-search/file-search-stores) and File Search
  [Documents](/api-reference/file-search/documents).

