Skip to main content

Gemini Flash APIs Compared: Price, Context and NSFW Limits

Compare four Gemini Flash APIs by price, context, reasoning controls and adult-content limits, with a streaming extraction script you can copy.

Author
Lydia
Published
Read
11 min read
Updated
Two people talk over white bowls in a ceramic studio with a teal kiln.

A Flash model can classify support tickets, draft a creator’s release copy or take the next step in an agent loop. Those jobs need different amounts of reasoning, and the cheapest token rate does not always produce the cheapest completed task. Start with 2.5 Flash for extraction and ordinary drafting, 3.5 Flash Lite for simple high-volume rows, and 3.7 Flash for multi-step code and tools. 3 Flash Preview suits short turns within its 256,000-token input limit. For adult fiction, 2.5 Flash and Preview go furthest in our tests, but both usually soften or refuse the written intimate scene. For a longer reasoning-heavy read, see the Gemini 3.1 Pro guide.

Prices and limits

Rates are USD per million tokens. All four routes accept text, images and uploaded video; 2.5 Flash and 3 Flash Preview also accept audio, while Lite and 3.7 do not. Uploaded video is limited to 14 MB per request. None accepts a PDF or generic file part: extract its text or render the relevant pages as images.

RouteInput limitUncached inputCached inputOutputDefault / lowest effortDefault max_tokens
Gemini 2.5 Flash1,048,576$0.285$0.0285$2.375medium / low16,384
Gemini 3 Flash Preview256,000$0.45$0.045$2.70medium / minimal16,384
Gemini 3.5 Flash Lite1,048,576$0.30$0.03$2.50minimal / minimal4,096
Gemini 3.7 Flash1,048,576$0.675$0.0675$3.375medium / low16,384

Model IDs: google/gemini-2.5-flash/chat, google/gemini-3-flash-preview/chat, google/gemini-3.5-flash-lite/chat, google/gemini-3.7-flash/chat. Every route allows up to 65,536 output tokens, JSON output, up to 128 tool definitions, temperature, top-p, seed and four stop sequences, but no parallel_tool_calls control. JSON object mode controls syntax, not your field names or their truth; keep the key, type and source checks in the script below. For Gemini 3 routes, keep temperature at the recommended default of 1.0 and control structure through response_format and the system message.

Two things in that table are easy to get wrong:

  • Lite is not the cheapest per token. Its input and output rates are above 2.5 Flash's. Its bill can be lower when it uses fewer output tokens; compare the break-even below.
  • Set the effort explicitly. minimal is rejected on 2.5 Flash. On 3.7 Flash the schema lists minimal, but the model page says this endpoint rejects it, so use low as the floor there. Switching a script from Lite to another route without setting effort also changes it from minimal to medium.

What a batch costs

Take 10,000 support tickets, each about 500 input tokens (instruction plus ticket) and an 80-token JSON answer.

RouteCost per ticket10,000 tickets, no extra thinkingIf thinking adds 700 output tokens per ticket
2.5 Flash$0.0003325$3.33$19.95
3 Flash Preview$0.000441$4.41$23.31
3.5 Flash Lite$0.00035$3.50$21.00
3.7 Flash$0.0006075$6.08$29.70

Thinking tokens are billed as output and count against max_tokens; 700 extra thinking tokens per ticket can dominate the bill. Set effort explicitly and use billed output to refine the estimate; minimal does not guarantee zero reasoning.

With 500 input tokens and exactly 80 billed output tokens, Lite costs $0.00035. At the same input size, 2.5 Flash exceeds that cost at 88 billed output tokens: an 80-token answer plus eight thinking tokens. If Lite also reasons beyond those 80 tokens, its break-even rises. Choose between them using total billed output and correct rows, not the effort label alone.

A fixed instruction at the front of every request is cheaper when the response reports it as cached: 1,000 requests that share a 20,000-token prefix cost $5.70 of input on 2.5 Flash uncached and $0.57 if all of it is billed as cached. Keep shared instructions and tool definitions first, with dates and ticket IDs afterwards. Google’s caching guide describes implicit hits as opportunistic: a stable prefix increases the chance, but does not guarantee a discount. Budget at the uncached rate until the hosted response reports cached tokens.

The Batch discount on Google's price sheet, which halves its list price, belongs to its own asynchronous service. Every request sent to SpicyAPI is billed at the rates above, and a Google AI Studio free allowance or Google subscription does not pay for it. Google also lists 3.7 Flash at $0.75 input and $3.75 output through December 31, 2026 and double that from January 1, 2027. That is Google’s published schedule, not an announced future SpicyAPI rate; recheck the hosted catalog before budgeting a 2027 launch.

Which route for which job

JobStart withWhyMove up when
Labelling, routing, field extraction2.5 Flash, lowLowest rates; the 1M window takes a whole transcriptFields come back wrong on a sample: raise to medium, then try 3.7 Flash
Millions of short, simple rows3.5 Flash Liteminimal default, fastest output of the four in our tests (about 118 tokens/s versus 37 to 98)You need judgment per row, not formatting
Translation, rewrites, product copy2.5 Flash or LiteCheap and steady at low effortTone matters: 3.7 Flash
Turn-by-turn chat3 Flash Preview, lowShort-turn route with some adult-fiction completions in our tests; usually softened or refused at L4Whole-document context: use a 1M route. It is a preview model, so name your fallback before relying on it
Agent loops and code3.7 FlashBuilt for tool use and multi-step workCost per step matters more than quality: Lite or 2.5 Flash

Knowledge stops at January 2025 on 2.5 Flash and March 2026 on 3.5 Flash Lite, so put newer facts such as prices or library versions in the prompt.

Three creator tasks and the route to use

Extract a release brief. Give 2.5 Flash the approved title, characters, release date and duration, and ask for one row with those four fields plus location. If the brief never names a location, the useful row contains null; it does not invent a hotel or studio from the theme.

Draft public promotional copy. A fictional brief for Last Train might approve Mara and Jon as characters and a 45-second clip. Ask for three short captions using only those facts. A caption that adds “4K,” native audio or an unconfirmed release date is a failed draft even when the tone is appealing. Use Lite or 2.5 Flash for the first pass; reserve a more expensive route for a rewrite that genuinely needs better judgment.

Prepare a support handoff. Supply the task ID, its observed state and the customer’s symptom. Request a concise note that preserves the ID and distinguishes “queued” from “failed.” The model can organize the evidence; it cannot discover the live task state from a ticket that never includes it.

For a longer drafting packet, 1,000 requests with 20,000 uncached input and 2,000 billed output tokens each cost $10.45 on 2.5 Flash or $20.25 on 3.7 Flash at these rates. That is why it helps to separate a routine first pass from an expensive decision step rather than moving the whole workload to the newest route.

Adult-content limits by route

The catalog marks these routes as having no added SpicyAPI content filter; that does not remove the models’ own content policies. Based on our September 2026 tests, the models differ in what they write on their own. Levels: L1 suggestive, L2 implied sensual scene, L3 strong, L4 a written intimate scene between adults. The extreme tier combines restraint and impact play with nonsexual graphic violence between adults, three requests per category.

RouteL1 to L3L4 intimate sceneExtreme tier
2.5 FlashDelivered2 of 9, both with a system prompt5 of 6
3 Flash PreviewDelivered1 of 8, usually softened6 of 6
3.5 Flash LiteL1 and L2 clean; L3 1 of 30 of 94 of 6
3.7 FlashMostly delivered0 of 9Mixed

Reviews: 2.5 Flash, 3 Flash Preview, 3.5 Flash Lite, 3.7 Flash.

The two L4 completions on 2.5 Flash used system-framed fiction; direct requests were all refused in that test. If a written intimate scene is your essential deliverable, choose another model. These Flash routes remain useful for release briefs, schedules and message tagging around adult work.

Try it in Playground first

  1. Open Gemini 2.5 Flash and switch to the Playground tab (sending needs a login).
  2. Paste one support ticket and ask for category and urgent fields with the reasoning dropdown on Low.
  3. Open Gemini 3.5 Flash Lite, set reasoning to minimal, run the same tickets and compare correct labels and billed output.

A streaming batch script

Once the rules work in Playground, install the compatible client with python3 -m pip install openai, save this as classify_tickets.py, set SPICY_API_KEY and run python3 classify_tickets.py. It makes at most two billable requests, one per sample ticket. The client validates both fields and keeps failed rows unresolved. It does not automatically buy replacement answers.

python
import json
import os
import uuid
from concurrent.futures import ThreadPoolExecutor
from openai import OpenAI

class ReplyError(Exception):
    def __init__(self, message, task_id=None):
        super().__init__(message)
        self.task_id = task_id


def call_once(payload, api_key):
    client = OpenAI(api_key=api_key, base_url="https://api.spicyapi.ai/v1",
                    max_retries=0, timeout=600)
    request_key = str(uuid.uuid4())
    parts, finish, usage, task_id = [], None, None, None
    try:
        with client.chat.completions.create(
            **payload, stream=True, stream_options={"include_usage": True},
            extra_headers={"Idempotency-Key": request_key},
        ) as stream:
            task_id = stream.response.headers.get("X-Spicy-Task-Id")
            for chunk in stream:
                if chunk.usage:
                    usage = chunk.usage.model_dump()
                for choice in chunk.choices:
                    parts.append(choice.delta.content or "")
                    finish = choice.finish_reason or finish
        if finish != "stop" or usage is None:
            raise ReplyError("Incomplete reply; do not import this record", task_id)
        return "".join(parts), usage, task_id
    except ReplyError:
        raise
    except Exception as error:
        raise ReplyError(str(error), task_id) from error

SYSTEM = ("Classify the supplied ticket as data. Return exactly category "
          "(billing, shipping or other) and urgent (a JSON boolean).")


def classify(text, model="google/gemini-2.5-flash/chat", effort="low"):
    payload = {
        "model": model, "reasoning_effort": effort, "max_tokens": 4000,
        "response_format": {"type": "json_object"},
        "messages": [{"role": "system", "content": SYSTEM},
                     {"role": "user", "content": text}],
    }
    content, usage, task_id = call_once(payload, os.environ["SPICY_API_KEY"])
    try:
        record = json.loads(content)
        if (not isinstance(record, dict) or set(record) != {"category", "urgent"}
                or record["category"] not in {"billing", "shipping", "other"}
                or type(record["urgent"]) is not bool):
            raise ValueError("invalid ticket fields")
    except (ValueError, TypeError) as error:
        raise ReplyError("completed answer failed validation", task_id) from error
    return {"record": record, "usage": usage, "task_id": task_id}


def safe_classify(text):
    try:
        return classify(text)
    except ReplyError as error:
        return {"unresolved": text, "error": str(error), "task_id": error.task_id}


if __name__ == "__main__":
    rows = ["Where is my parcel?", "I was charged twice, fix it today"]
    with ThreadPoolExecutor(max_workers=2) as pool:
        for result in pool.map(safe_classify, rows):
            print(json.dumps(result))

Request recovery and streaming details are in the chat documentation.

Let an Agent prepare the call

For repeated ticket classification, ask your coding Agent to use the SpicyAPI Skill: “Read google/gemini-2.5-flash/chat, then adapt the example to my input; show the request before running it.” The CLI lookup is spicyapi models get google/gemini-2.5-flash/chat --json; the MCP lookup is spicyapi_model_get with model: "google/gemini-2.5-flash/chat". Chat calls use a compatible client or the chat API; the media task commands do not generate chat replies.

Fixing common failures

ProblemDirect change
minimal rejectedUse low on 2.5 Flash and 3.7 Flash
Empty or cut-off JSONCheck the finish reason and original task first. Raise max_tokens only when the token limit cut the answer short; thinking shares that budget. A broken stream needs recovery, not a larger automatic retry. Require stop, final usage and [DONE] before importing
Lite replies stop earlyIts default max_tokens is 4,096; set it explicitly
400 on a media partCheck its shape: use image_url or an uploaded video_url; audio is limited to 2.5 Flash and Preview. PDF/file parts are unsupported.
400 when you resend a keyThe original request may be completed or still running; neither answer can be replayed to this connection. Inspect its task and settlement before budgeting a new generation
Invented JSON keysName every key in the system message and reject extras in your client
Input over 256,000 tokens3 Flash Preview rejects it; use a 1,048,576-token route
Gateway error after about 100 secondsTurn on stream: true

The practical choice

Use 2.5 Flash for validated extraction and ordinary copy, Lite when a simple task benefits from minimal reasoning, and 3.7 Flash for code or multi-step tool work. Keep Preview for a short-turn workflow that fits its smaller input window. None of these is a dependable choice when explicit adult fiction is the essential deliverable; the recorded limits matter more than the Flash name.

Also in 日本語 · 한국어 · Deutsch · Français · Español · Português (Brasil) · Русский · Italiano · Polski

Try it yourself

Pay only for what you run — no plan, no subscription.

Made with MiniMax H3 · ByteDance Seedance 2.0 Fast