Repository Public
1Gemini models can process documents in PDF format, using native2vision to understand entire document contexts. This goes beyond3just text extraction, allowing Gemini to:45- Analyze and interpret content, including text, images, diagrams, charts, and tables, even in long documents up to 1000 pages.6- Extract information into [structured output](https://ai.google.dev/gemini-api/docs/structured-output) formats.7- Summarize and answer questions based on both the visual and textual elements in a document.8- Transcribe document content (e.g. to HTML), preserving layouts and formatting, for use in downstream applications.910You can also pass non-PDF documents in the same way but Gemini will see them11as normal text which will eliminate context like charts or formatting.1213## Passing PDF data inline1415You can pass PDF data inline in the request to `generateContent`. This is best16suited for smaller documents or temporary processing where you don't need to17reference the file in subsequent requests. We recommend using the [Files API](https://ai.google.dev/gemini-api/docs/document-processing#large-pdfs)18for larger documents that you need to refer to in multi-turn interactions to19improve request latency and reduce bandwidth usage.2021The following example shows you how to fetch a PDF from a URL and convert it to22bytes for processing:2324### Python2526 from google import genai27 from google.genai import types28 import httpx2930 client = genai.Client()3132 doc_url = "https://discovery.ucl.ac.uk/id/eprint/10089234/1/343019_3_art_0_py4t4l_convrt.pdf"3334 # Retrieve and encode the PDF byte35 doc_data = httpx.get(doc_url).content3637 prompt = "Summarize this document"38 response = client.models.generate_content(39 model="gemini-3.8-flash",40 contents=[41 types.Part.from_bytes(42 data=doc_data,43 mime_type='application/pdf',44 ),45 prompt46 ]47 )4849 print(response.text)5051### JavaScript5253 import { GoogleGenAI } from "@google/genai";5455 const ai = new GoogleGenAI({ apiKey: "GEMINI_API_KEY" });5657 async function main() {58 const pdfResp = await fetch('https://discovery.ucl.ac.uk/id/eprint/10089234/1/343019_3_art_0_py4t4l_convrt.pdf')59 .then((response) => response.arrayBuffer());6061 const contents = [62 { text: "Summarize this document" },63 {64 inlineData: {65 mimeType: 'application/pdf',66 data: Buffer.from(pdfResp).toString("base64")67 }68 }69 ];7071 const response = await ai.models.generateContent({72 model: "gemini-3.8-flash",73 contents: contents74 });75 console.log(response.text);76 }7778 main();7980### Go8182 package main8384 import (85 "context"86 "fmt"87 "io"88 "net/http"89 "os"90 "google.golang.org/genai"91 )9293 func main() {9495 ctx := context.Background()96 client, _ := genai.NewClient(ctx, &genai.ClientConfig{97 APIKey: os.Getenv("GEMINI_API_KEY"),98 Backend: genai.BackendGeminiAPI,99 })100101 pdfResp, _ := http.Get("https://discovery.ucl.ac.uk/id/eprint/10089234/1/343019_3_art_0_py4t4l_convrt.pdf")102 var pdfBytes []byte103 if pdfResp != nil && pdfResp.Body != nil {104 pdfBytes, _ = io.ReadAll(pdfResp.Body)105 pdfResp.Body.Close()106 }107108 parts := []*genai.Part{109 &genai.Part{110 InlineData: &genai.Blob{111 MIMEType: "application/pdf",112 Data: pdfBytes,113 },114 },115 genai.NewPartFromText("Summarize this document"),116 }117118 contents := []*genai.Content{119 genai.NewContentFromParts(parts, genai.RoleUser),120 }121122 result, _ := client.Models.GenerateContent(123 ctx,124 "gemini-3.8-flash",125 contents,126 nil,127 )128129 fmt.Println(result.Text())130 }131132### REST133134 DOC_URL="https://discovery.ucl.ac.uk/id/eprint/10089234/1/343019_3_art_0_py4t4l_convrt.pdf"135 PROMPT="Summarize this document"136 DISPLAY_NAME="base64_pdf"137138 # Download the PDF139 wget -O "${DISPLAY_NAME}.pdf" "${DOC_URL}"140141 # Check for FreeBSD base64 and set flags accordingly142 if [[ "$(base64 --version 2>&1)" = *"FreeBSD"* ]]; then143 B64FLAGS="--input"144 else145 B64FLAGS="-w0"146 fi147148 # Base64 encode the PDF149 ENCODED_PDF=$(base64 $B64FLAGS "${DISPLAY_NAME}.pdf")150151 # Generate content using the base64 encoded PDF152 curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent?key=$GOOGLE_API_KEY" \153 -H 'Content-Type: application/json' \154 -X POST \155 -d '{156 "contents": [{157 "parts":[158 {"inline_data": {"mime_type": "application/pdf", "data": "'"$ENCODED_PDF"'"}},159 {"text": "'$PROMPT'"}160 ]161 }]162 }' 2> /dev/null > response.json163164 cat response.json165 echo166167 jq ".candidates[].content.parts[].text" response.json168169 # Clean up the downloaded PDF170 rm "${DISPLAY_NAME}.pdf"171172You can also read a PDF from a local file for processing:173174### Python175176 from google import genai177 from google.genai import types178 import pathlib179180 client = genai.Client()181182 # Retrieve and encode the PDF byte183 filepath = pathlib.Path('file.pdf')184185 prompt = "Summarize this document"186 response = client.models.generate_content(187 model="gemini-3.8-flash",188 contents=[189 types.Part.from_bytes(190 data=filepath.read_bytes(),191 mime_type='application/pdf',192 ),193 prompt])194 print(response.text)195196### JavaScript197198 import { GoogleGenAI } from "@google/genai";199 import * as fs from 'fs';200201 const ai = new GoogleGenAI({ apiKey: "GEMINI_API_KEY" });202203 async function main() {204 const contents = [205 { text: "Summarize this document" },206 {207 inlineData: {208 mimeType: 'application/pdf',209 data: Buffer.from(fs.readFileSync("content/343019_3_art_0_py4t4l_convrt.pdf")).toString("base64")210 }211 }212 ];213214 const response = await ai.models.generateContent({215 model: "gemini-3.8-flash",216 contents: contents217 });218 console.log(response.text);219 }220221 main();222223### Go224225 package main226227 import (228 "context"229 "fmt"230 "os"231 "google.golang.org/genai"232 )233234 func main() {235236 ctx := context.Background()237 client, _ := genai.NewClient(ctx, &genai.ClientConfig{238 APIKey: os.Getenv("GEMINI_API_KEY"),239 Backend: genai.BackendGeminiAPI,240 })241242 pdfBytes, _ := os.ReadFile("path/to/your/file.pdf")243244 parts := []*genai.Part{245 &genai.Part{246 InlineData: &genai.Blob{247 MIMEType: "application/pdf",248 Data: pdfBytes,249 },250 },251 genai.NewPartFromText("Summarize this document"),252 }253 contents := []*genai.Content{254 genai.NewContentFromParts(parts, genai.RoleUser),255 }256257 result, _ := client.Models.GenerateContent(258 ctx,259 "gemini-3.8-flash",260 contents,261 nil,262 )263264 fmt.Println(result.Text())265 }266267## Uploading PDFs using the Files API268269We recommend you use Files API for larger files or when you intend to reuse a270document across multiple requests. This improves request latency and reduces271bandwidth usage by decoupling the file upload from the model requests.272273> [!NOTE]274> **Note:** The Files API is available at no cost in all regions where the Gemini API is available. Uploaded files are stored for 48 hours.275276### Large PDFs from URLs277278Use the File API to simplify uploading and processing large PDF files from URLs:279280### Python281282 from google import genai283 from google.genai import types284 import io285 import httpx286287 client = genai.Client()288289 long_context_pdf_path = "https://www.nasa.gov/wp-content/uploads/static/history/alsj/a17/A17_FlightPlan.pdf"290291 # Retrieve and upload the PDF using the File API292 doc_io = io.BytesIO(httpx.get(long_context_pdf_path).content)293294 sample_doc = client.files.upload(295 # You can pass a path or a file-like object here296 file=doc_io,297 config=dict(298 mime_type='application/pdf')299 )300301 prompt = "Summarize this document"302303 response = client.models.generate_content(304 model="gemini-3.8-flash",305 contents=[sample_doc, prompt])306 print(response.text)307308### JavaScript309310 import { createPartFromUri, GoogleGenAI } from "@google/genai";311312 const ai = new GoogleGenAI({ apiKey: "GEMINI_API_KEY" });313314 async function main() {315316 const pdfBuffer = await fetch("https://www.nasa.gov/wp-content/uploads/static/history/alsj/a17/A17_FlightPlan.pdf")317 .then((response) => response.arrayBuffer());318319 const fileBlob = new Blob([pdfBuffer], { type: 'application/pdf' });320321 const file = await ai.files.upload({322 file: fileBlob,323 config: {324 displayName: 'A17_FlightPlan.pdf',325 },326 });327328 // Wait for the file to be processed.329 let getFile = await ai.files.get({ name: file.name });330 while (getFile.state === 'PROCESSING') {331 getFile = await ai.files.get({ name: file.name });332 console.log(`current file status: ${getFile.state}`);333 console.log('File is still processing, retrying in 5 seconds');334335 await new Promise((resolve) => {336 setTimeout(resolve, 5000);337 });338 }339 if (file.state === 'FAILED') {340 throw new Error('File processing failed.');341 }342343 // Add the file to the contents.344 const content = [345 'Summarize this document',346 ];347348 if (file.uri && file.mimeType) {349 const fileContent = createPartFromUri(file.uri, file.mimeType);350 content.push(fileContent);351 }352353 const response = await ai.models.generateContent({354 model: 'gemini-3.8-flash',355 contents: content,356 });357358 console.log(response.text);359360 }361362 main();363364### Go365366 package main367368 import (369 "context"370 "fmt"371 "io"372 "net/http"373 "os"374 "google.golang.org/genai"375 )376377 func main() {378379 ctx := context.Background()380 client, _ := genai.NewClient(ctx, &genai.ClientConfig{381 APIKey: os.Getenv("GEMINI_API_KEY"),382 Backend: genai.BackendGeminiAPI,383 })384385 pdfURL := "https://www.nasa.gov/wp-content/uploads/static/history/alsj/a17/A17_FlightPlan.pdf"386 localPdfPath := "A17_FlightPlan_downloaded.pdf"387388 respHttp, _ := http.Get(pdfURL)389 defer respHttp.Body.Close()390391 outFile, _ := os.Create(localPdfPath)392 defer outFile.Close()393394 _, _ = io.Copy(outFile, respHttp.Body)395396 uploadConfig := &genai.UploadFileConfig{MIMEType: "application/pdf"}397 uploadedFile, _ := client.Files.UploadFromPath(ctx, localPdfPath, uploadConfig)398399 promptParts := []*genai.Part{400 genai.NewPartFromURI(uploadedFile.URI, uploadedFile.MIMEType),401 genai.NewPartFromText("Summarize this document"),402 }403 contents := []*genai.Content{404 genai.NewContentFromParts(promptParts, genai.RoleUser), // Specify role405 }406407 result, _ := client.Models.GenerateContent(408 ctx,409 "gemini-3.8-flash",410 contents,411 nil,412 )413414 fmt.Println(result.Text())415 }416417### REST418419 PDF_PATH="https://www.nasa.gov/wp-content/uploads/static/history/alsj/a17/A17_FlightPlan.pdf"420 DISPLAY_NAME="A17_FlightPlan"421 PROMPT="Summarize this document"422423 # Download the PDF from the provided URL424 wget -O "${DISPLAY_NAME}.pdf" "${PDF_PATH}"425426 MIME_TYPE=$(file -b --mime-type "${DISPLAY_NAME}.pdf")427 NUM_BYTES=$(wc -c < "${DISPLAY_NAME}.pdf")428429 echo "MIME_TYPE: ${MIME_TYPE}"430 echo "NUM_BYTES: ${NUM_BYTES}"431432 tmp_header_file=upload-header.tmp433434 # Initial resumable request defining metadata.435 # The upload url is in the response headers dump them to a file.436 curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \437 -D upload-header.tmp \438 -H "X-Goog-Upload-Protocol: resumable" \439 -H "X-Goog-Upload-Command: start" \440 -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \441 -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \442 -H "Content-Type: application/json" \443 -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null444445 upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r")446 rm "${tmp_header_file}"447448 # Upload the actual bytes.449 curl "${upload_url}" \450 -H "Content-Length: ${NUM_BYTES}" \451 -H "X-Goog-Upload-Offset: 0" \452 -H "X-Goog-Upload-Command: upload, finalize" \453 --data-binary "@${DISPLAY_NAME}.pdf" 2> /dev/null > file_info.json454455 file_uri=$(jq ".file.uri" file_info.json)456 echo "file_uri: ${file_uri}"457458 # Now generate content using that file459 curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent?key=$GOOGLE_API_KEY" \460 -H 'Content-Type: application/json' \461 -X POST \462 -d '{463 "contents": [{464 "parts":[465 {"text": "'$PROMPT'"},466 {"file_data":{"mime_type": "application/pdf", "file_uri": '$file_uri'}}]467 }]468 }' 2> /dev/null > response.json469470 cat response.json471 echo472473 jq ".candidates[].content.parts[].text" response.json474475 # Clean up the downloaded PDF476 rm "${DISPLAY_NAME}.pdf"477478### Large PDFs stored locally479480### Python481482 from google import genai483 from google.genai import types484 import pathlib485 import httpx486487 client = genai.Client()488489 # Retrieve and encode the PDF byte490 file_path = pathlib.Path('large_file.pdf')491492 # Upload the PDF using the File API493 sample_file = client.files.upload(494 file=file_path,495 )496497 prompt="Summarize this document"498499 response = client.models.generate_content(500 model="gemini-3.8-flash",501 contents=[sample_file, "Summarize this document"])502 print(response.text)503504### JavaScript505506 import { createPartFromUri, GoogleGenAI } from "@google/genai";507508 const ai = new GoogleGenAI({ apiKey: "GEMINI_API_KEY" });509510 async function main() {511 const file = await ai.files.upload({512 file: 'path-to-localfile.pdf'513 config: {514 displayName: 'A17_FlightPlan.pdf',515 },516 });517518 // Wait for the file to be processed.519 let getFile = await ai.files.get({ name: file.name });520 while (getFile.state === 'PROCESSING') {521 getFile = await ai.files.get({ name: file.name });522 console.log(`current file status: ${getFile.state}`);523 console.log('File is still processing, retrying in 5 seconds');524525 await new Promise((resolve) => {526 setTimeout(resolve, 5000);527 });528 }529 if (file.state === 'FAILED') {530 throw new Error('File processing failed.');531 }532533 // Add the file to the contents.534 const content = [535 'Summarize this document',536 ];537538 if (file.uri && file.mimeType) {539 const fileContent = createPartFromUri(file.uri, file.mimeType);540 content.push(fileContent);541 }542543 const response = await ai.models.generateContent({544 model: 'gemini-3.8-flash',545 contents: content,546 });547548 console.log(response.text);549550 }551552 main();553554### Go555556 package main557558 import (559 "context"560 "fmt"561 "os"562 "google.golang.org/genai"563 )564565 func main() {566567 ctx := context.Background()568 client, _ := genai.NewClient(ctx, &genai.ClientConfig{569 APIKey: os.Getenv("GEMINI_API_KEY"),570 Backend: genai.BackendGeminiAPI,571 })572 localPdfPath := "/path/to/file.pdf"573574 uploadConfig := &genai.UploadFileConfig{MIMEType: "application/pdf"}575 uploadedFile, _ := client.Files.UploadFromPath(ctx, localPdfPath, uploadConfig)576577 promptParts := []*genai.Part{578 genai.NewPartFromURI(uploadedFile.URI, uploadedFile.MIMEType),579 genai.NewPartFromText("Give me a summary of this pdf file."),580 }581 contents := []*genai.Content{582 genai.NewContentFromParts(promptParts, genai.RoleUser),583 }584585 result, _ := client.Models.GenerateContent(586 ctx,587 "gemini-3.8-flash",588 contents,589 nil,590 )591592 fmt.Println(result.Text())593 }594595### REST596597 NUM_BYTES=$(wc -c < "${PDF_PATH}")598 DISPLAY_NAME=TEXT599 tmp_header_file=upload-header.tmp600601 # Initial resumable request defining metadata.602 # The upload url is in the response headers dump them to a file.603 curl "${BASE_URL}/upload/v1beta/files?key=${GEMINI_API_KEY}" \604 -D upload-header.tmp \605 -H "X-Goog-Upload-Protocol: resumable" \606 -H "X-Goog-Upload-Command: start" \607 -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \608 -H "X-Goog-Upload-Header-Content-Type: application/pdf" \609 -H "Content-Type: application/json" \610 -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null611612 upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r")613 rm "${tmp_header_file}"614615 # Upload the actual bytes.616 curl "${upload_url}" \617 -H "Content-Length: ${NUM_BYTES}" \618 -H "X-Goog-Upload-Offset: 0" \619 -H "X-Goog-Upload-Command: upload, finalize" \620 --data-binary "@${PDF_PATH}" 2> /dev/null > file_info.json621622 file_uri=$(jq ".file.uri" file_info.json)623 echo file_uri=$file_uri624625 # Now generate content using that file626 curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent?key=$GOOGLE_API_KEY" \627 -H 'Content-Type: application/json' \628 -X POST \629 -d '{630 "contents": [{631 "parts":[632 {"text": "Can you add a few more lines to this poem?"},633 {"file_data":{"mime_type": "application/pdf", "file_uri": '$file_uri'}}]634 }]635 }' 2> /dev/null > response.json636637 cat response.json638 echo639640 jq ".candidates[].content.parts[].text" response.json641642You can verify the API successfully stored the uploaded file and get its643metadata by calling [`files.get`](https://ai.google.dev/api/rest/v1beta/files/get). Only the `name`644(and by extension, the `uri`) are unique.645646### Python647648 from google import genai649 import pathlib650651 client = genai.Client()652653 fpath = pathlib.Path('example.txt')654 fpath.write_text('hello')655656 file = client.files.upload(file='example.txt')657658 file_info = client.files.get(name=file.name)659 print(file_info.model_dump_json(indent=4))660661### REST662663 name=$(jq ".file.name" file_info.json)664 # Get the file of interest to check state665 curl https://generativelanguage.googleapis.com/v1beta/files/$name > file_info.json666 # Print some information about the file you got667 name=$(jq ".file.name" file_info.json)668 echo name=$name669 file_uri=$(jq ".file.uri" file_info.json)670 echo file_uri=$file_uri671672## Passing multiple PDFs673674The Gemini API is capable of processing multiple PDF documents (up to 1000 pages)675in a single request, as long as the combined size of the documents and the text676prompt stays within the model's context window.677678### Python679680 from google import genai681 import io682 import httpx683684 client = genai.Client()685686 doc_url_1 = "https://arxiv.org/pdf/2312.11805"687 doc_url_2 = "https://arxiv.org/pdf/2403.05530"688689 # Retrieve and upload both PDFs using the File API690 doc_data_1 = io.BytesIO(httpx.get(doc_url_1).content)691 doc_data_2 = io.BytesIO(httpx.get(doc_url_2).content)692693 sample_pdf_1 = client.files.upload(694 file=doc_data_1,695 config=dict(mime_type='application/pdf')696 )697 sample_pdf_2 = client.files.upload(698 file=doc_data_2,699 config=dict(mime_type='application/pdf')700 )701702 prompt = "What is the difference between each of the main benchmarks between these two papers? Output these in a table."703704 response = client.models.generate_content(705 model="gemini-3.8-flash",706 contents=[sample_pdf_1, sample_pdf_2, prompt]707 )708709 print(response.text)710711### JavaScript712713 import { createPartFromUri, GoogleGenAI } from "@google/genai";714715 const ai = new GoogleGenAI({ apiKey: "GEMINI_API_KEY" });716717 async function uploadRemotePDF(url, displayName) {718 const pdfBuffer = await fetch(url)719 .then((response) => response.arrayBuffer());720721 const fileBlob = new Blob([pdfBuffer], { type: 'application/pdf' });722723 const file = await ai.files.upload({724 file: fileBlob,725 config: {726 displayName: displayName,727 },728 });729730 // Wait for the file to be processed.731 let getFile = await ai.files.get({ name: file.name });732 while (getFile.state === 'PROCESSING') {733 getFile = await ai.files.get({ name: file.name });734 console.log(`current file status: ${getFile.state}`);735 console.log('File is still processing, retrying in 5 seconds');736737 await new Promise((resolve) => {738 setTimeout(resolve, 5000);739 });740 }741 if (file.state === 'FAILED') {742 throw new Error('File processing failed.');743 }744745 return file;746 }747748 async function main() {749 const content = [750 'What is the difference between each of the main benchmarks between these two papers? Output these in a table.',751 ];752753 let file1 = await uploadRemotePDF("https://arxiv.org/pdf/2312.11805", "PDF 1")754 if (file1.uri && file1.mimeType) {755 const fileContent = createPartFromUri(file1.uri, file1.mimeType);756 content.push(fileContent);757 }758 let file2 = await uploadRemotePDF("https://arxiv.org/pdf/2403.05530", "PDF 2")759 if (file2.uri && file2.mimeType) {760 const fileContent = createPartFromUri(file2.uri, file2.mimeType);761 content.push(fileContent);762 }763764 const response = await ai.models.generateContent({765 model: 'gemini-3.8-flash',766 contents: content,767 });768769 console.log(response.text);770 }771772 main();773774### Go775776 package main777778 import (779 "context"780 "fmt"781 "io"782 "net/http"783 "os"784 "google.golang.org/genai"785 )786787 func main() {788789 ctx := context.Background()790 client, _ := genai.NewClient(ctx, &genai.ClientConfig{791 APIKey: os.Getenv("GEMINI_API_KEY"),792 Backend: genai.BackendGeminiAPI,793 })794795 docUrl1 := "https://arxiv.org/pdf/2312.11805"796 docUrl2 := "https://arxiv.org/pdf/2403.05530"797 localPath1 := "doc1_downloaded.pdf"798 localPath2 := "doc2_downloaded.pdf"799800 respHttp1, _ := http.Get(docUrl1)801 defer respHttp1.Body.Close()802803 outFile1, _ := os.Create(localPath1)804 _, _ = io.Copy(outFile1, respHttp1.Body)805 outFile1.Close()806807 respHttp2, _ := http.Get(docUrl2)808 defer respHttp2.Body.Close()809810 outFile2, _ := os.Create(localPath2)811 _, _ = io.Copy(outFile2, respHttp2.Body)812 outFile2.Close()813814 uploadConfig1 := &genai.UploadFileConfig{MIMEType: "application/pdf"}815 uploadedFile1, _ := client.Files.UploadFromPath(ctx, localPath1, uploadConfig1)816817 uploadConfig2 := &genai.UploadFileConfig{MIMEType: "application/pdf"}818 uploadedFile2, _ := client.Files.UploadFromPath(ctx, localPath2, uploadConfig2)819820 promptParts := []*genai.Part{821 genai.NewPartFromURI(uploadedFile1.URI, uploadedFile1.MIMEType),822 genai.NewPartFromURI(uploadedFile2.URI, uploadedFile2.MIMEType),823 genai.NewPartFromText("What is the difference between each of the " +824 "main benchmarks between these two papers? " +825 "Output these in a table."),826 }827 contents := []*genai.Content{828 genai.NewContentFromParts(promptParts, genai.RoleUser),829 }830831 modelName := "gemini-3.8-flash"832 result, _ := client.Models.GenerateContent(833 ctx,834 modelName,835 contents,836 nil,837 )838839 fmt.Println(result.Text())840 }841842### REST843844 DOC_URL_1="https://arxiv.org/pdf/2312.11805"845 DOC_URL_2="https://arxiv.org/pdf/2403.05530"846 DISPLAY_NAME_1="Gemini_paper"847 DISPLAY_NAME_2="Gemini_1.5_paper"848 PROMPT="What is the difference between each of the main benchmarks between these two papers? Output these in a table."849850 # Function to download and upload a PDF851 upload_pdf() {852 local doc_url="$1"853 local display_name="$2"854855 # Download the PDF856 wget -O "${display_name}.pdf" "${doc_url}"857858 local MIME_TYPE=$(file -b --mime-type "${display_name}.pdf")859 local NUM_BYTES=$(wc -c < "${display_name}.pdf")860861 echo "MIME_TYPE: ${MIME_TYPE}"862 echo "NUM_BYTES: ${NUM_BYTES}"863864 local tmp_header_file=upload-header.tmp865866 # Initial resumable request867 curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \868 -D "${tmp_header_file}" \869 -H "X-Goog-Upload-Protocol: resumable" \870 -H "X-Goog-Upload-Command: start" \871 -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \872 -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \873 -H "Content-Type: application/json" \874 -d "{'file': {'display_name': '${display_name}'}}" 2> /dev/null875876 local upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r")877 rm "${tmp_header_file}"878879 # Upload the PDF880 curl "${upload_url}" \881 -H "Content-Length: ${NUM_BYTES}" \882 -H "X-Goog-Upload-Offset: 0" \883 -H "X-Goog-Upload-Command: upload, finalize" \884 --data-binary "@${display_name}.pdf" 2> /dev/null > "file_info_${display_name}.json"885886 local file_uri=$(jq ".file.uri" "file_info_${display_name}.json")887 echo "file_uri for ${display_name}: ${file_uri}"888889 # Clean up the downloaded PDF890 rm "${display_name}.pdf"891892 echo "${file_uri}"893 }894895 # Upload the first PDF896 file_uri_1=$(upload_pdf "${DOC_URL_1}" "${DISPLAY_NAME_1}")897898 # Upload the second PDF899 file_uri_2=$(upload_pdf "${DOC_URL_2}" "${DISPLAY_NAME_2}")900901 # Now generate content using both files902 curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent?key=$GOOGLE_API_KEY" \903 -H 'Content-Type: application/json' \904 -X POST \905 -d '{906 "contents": [{907 "parts":[908 {"file_data": {"mime_type": "application/pdf", "file_uri": '$file_uri_1'}},909 {"file_data": {"mime_type": "application/pdf", "file_uri": '$file_uri_2'}},910 {"text": "'$PROMPT'"}911 ]912 }]913 }' 2> /dev/null > response.json914915 cat response.json916 echo917918 jq ".candidates[].content.parts[].text" response.json919920## Technical details921922Gemini supports PDF files up to 50MB or 1000 pages. This limit applies923to both inline data and Files API uploads. Each document page is equivalent to 258924tokens.925926While there are no specific limits to the number of pixels in a document besides927the model's [context window](https://ai.google.dev/gemini-api/docs/long-context), larger pages are928scaled down to a maximum resolution of 3072 x 3072 while preserving their original929aspect ratio, while smaller pages are scaled up to 768 x 768 pixels. There is no930cost reduction for pages at lower sizes, other than bandwidth, or performance931improvement for pages at higher resolution.932933### Gemini 3 models934935Gemini 3 introduces granular control over multimodal vision processing with the936`media_resolution` parameter. You can now set the resolution to low, medium, or937high per individual media part. With this addition, the processing of PDF938documents has been updated:9399401. **Native text inclusion:** Text natively embedded in the PDF is extracted and provided to the model.9412. **Billing \& token reporting:**942 - You are **not charged** for tokens originating from the extracted **native text** in PDFs.943 - In the `usage_metadata` section of the API response, tokens generated from processing PDF pages (as images) are now counted under the `IMAGE` modality, not a separate `DOCUMENT` modality as in some earlier versions.944945For more details about the media resolution parameter, see the946[Media resolution](https://ai.google.dev/gemini-api/docs/generate-content/media-resolution) guide.947948### Document types949950Technically, you can pass other MIME types for document understanding, like951TXT, Markdown, HTML, XML, etc. However, document vision ***only meaningfully952understands PDFs***. Other types will be extracted as pure text, and the model953won't be able to interpret what we see in the rendering of those files. Any954file-type specifics like charts, diagrams, HTML tags, Markdown formatting, etc.,955will be lost.956957To learn about other file input methods, see the958[File input methods](https://ai.google.dev/gemini-api/docs/file-input-methods) guide.959960### Best practices961962For best results:963964- Rotate pages to the correct orientation before uploading.965- Avoid blurry pages.966- If using a single page, place the text prompt after the page.967968## What's next969970To learn more, see the following resources:971972- [File prompting strategies](https://ai.google.dev/gemini-api/docs/files#prompt-guide): The Gemini API supports prompting with text, image, audio, and video data, also known as multimodal prompting.973- [System instructions](https://ai.google.dev/gemini-api/docs/text-generation#system-instructions): System instructions let you steer the behavior of the model based on your specific needs and use cases.