Jesse A. Green / notebook

Gradio User Guide

Generated June 2026 from gradio-app/gradio at e4e84a2

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

Gradio is an open-source Python library for building and sharing web apps for machine learning models, APIs, or any Python function — no JavaScript, CSS, or web-hosting experience required. You write a Python function, wrap it in a Gradio component layout, and call .launch(); Gradio renders a complete web UI, runs a server, and (optionally) creates a public share link in seconds.

This guide covers everything you need to build, customize, run, and share Gradio apps with the gradio Python package (version 6.x). It is organized by what you want to do — start with the Quick Start, then jump to the task that matches your goal.

Note

Gradio ships three high-level building blocks: gr.Interface (the fastest way to wrap a single function), gr.Blocks (full control over layout and data flow), and gr.ChatInterface (purpose-built for chatbots). All three are entirely Python.


1. Quick Start

1.1 Your first app

Create a file named app.py:

import gradio as gr

def greet(name, intensity):
    return "Hello, " + name + "!" * int(intensity)

demo = gr.Interface(
    fn=greet,
    inputs=["text", "slider"],
    outputs=["text"],
)

demo.launch()

Run it:

python app.py

Expected output:

* Running on local URL:  http://127.0.0.1:7860

To create a public link, set `share=True` in `launch()`.

Open http://127.0.0.1:7860 in your browser. Type a name, drag the slider, and click Submit — your greeting appears on the right.

Tip

By convention, Gradio is imported as gr (import gradio as gr) for readability. Every example in this guide follows that convention.

1.2 The three core arguments of gr.Interface

Argument Meaning
fn The Python function to wrap a UI around. Can be any callable — a model's predict, a generator, an async function.
inputs One component (or list) for the function's argument(s). The number of inputs must match the number of fn parameters.
outputs One component (or list) for the function's return value(s). The number of outputs must match the number of return values.

You can pass components either as string shortcuts ("text", "slider", "image") or as instantiated objects (gr.Textbox(), gr.Slider(), gr.Image()). Use the object form when you need to configure the component (labels, ranges, defaults).

demo = gr.Interface(
    fn=greet,
    inputs=[gr.Textbox(label="Your name"), gr.Slider(1, 10, value=3, label="Intensity")],
    outputs=[gr.Textbox(label="Greeting")],
)

1.3 Share it with the world

Set share=True to get a temporary public URL (valid ~72 hours), tunneled from your machine — no deployment needed:

demo.launch(share=True)
* Running on local URL:  http://127.0.0.1:7860
* Running on public URL: https://a23dsf231adb.gradio.live

This share link expires in 72 hours.

Important

With a share link, the UI is publicly reachable but all computation still runs on your machine. Do not share links to apps that expose sensitive data or that you have not secured with authentication.


2. Installation

Prerequisite: Gradio requires Python 3.10 or higher (3.10–3.13 are supported).

pip (recommended)

pip install --upgrade gradio

With OAuth support

pip install --upgrade "gradio[oauth]"

With MCP server support

pip install --upgrade "gradio[mcp]"

uv

uv add gradio

Verify the install:

python -c "import gradio; print(gradio.__version__)"
6.17.0

Tip

Always install Gradio inside a virtual environment to avoid dependency conflicts:

python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install gradio

The base install pulls in FastAPI, Starlette, Uvicorn, Pydantic, huggingface_hub, gradio_client, pandas, numpy, and pillow. The [oauth] and [mcp] extras add the dependencies needed for sign-in and MCP-server features respectively.


3. Choosing Your Building Block

Gradio gives you three ways to build, in increasing order of control:

Building block Use when you want to… Lines of code
gr.Interface Wrap a single function with fixed inputs → outputs (the classic "demo a model" case) Fewest
gr.ChatInterface Build a chatbot UI around a message-handling function Few
gr.Blocks Design custom layouts, multiple interacting functions, dynamic UIs, dashboards Most flexible

Note

gr.Interface and gr.ChatInterface are both built on top of gr.Blocks. Anything you can do with them, you can also do (more verbosely) with Blocks. Start high-level and drop to Blocks only when you need the control.


4. Building with gr.Interface

gr.Interface is the quickest path from a function to a demo. Beyond the three core arguments, it accepts many parameters to control appearance and behavior.

4.1 Multiple inputs and outputs

Pass lists. Each input maps to a function argument (in order); each output maps to a return value (in order):

import gradio as gr

def calculate(num1, operation, num2):
    if operation == "add":
        return num1 + num2, "Added!"
    elif operation == "multiply":
        return num1 * num2, "Multiplied!"

demo = gr.Interface(
    fn=calculate,
    inputs=[gr.Number(), gr.Radio(["add", "multiply"]), gr.Number()],
    outputs=[gr.Number(label="Result"), gr.Textbox(label="Status")],
)
demo.launch()

4.2 The four kinds of Interfaces

The shape of an Interface is inferred automatically from inputs/outputs:

Kind Condition Behavior
Standard Both inputs and outputs provided Input column → Submit → output column
Input-only outputs=None Collects input, no output panel
Output-only inputs=None "Generate" button produces output
Unified inputs and outputs are the same component objects One panel acting as both (e.g. an image editor)

4.3 Live interfaces

Set live=True to re-run automatically whenever any input changes — no Submit button:

gr.Interface(fn=greet, inputs="text", outputs="text", live=True).launch()

4.4 Examples

Provide sample inputs that users can click to populate the UI. Pass a nested list (one inner list per example, in input order):

gr.Interface(
    fn=calculate,
    inputs=[gr.Number(), gr.Radio(["add", "multiply"]), gr.Number()],
    outputs=[gr.Number(), gr.Textbox()],
    examples=[[3, "add", 4], [5, "multiply", 6]],
)

See Examples & Caching for caching and performance.

4.5 Titles, descriptions, and articles

gr.Interface(
    fn=greet,
    inputs="text",
    outputs="text",
    title="Greeting Generator",
    description="Enter your name to receive a friendly greeting. Supports **Markdown**.",
    article="A longer explanation that appears *below* the interface.",
)

description and article accept Markdown and HTML. If article is an HTTP(S) link to a file, its contents are downloaded and displayed.

4.6 Selected gr.Interface parameters

Parameter Default Purpose
live False Re-run automatically on input change
examples None Clickable sample inputs (nested list or directory path)
cache_examples None Pre-compute example outputs for instant display
title / description / article None Header/footer text (Markdown + HTML)
flagging_mode "manual" "never", "auto", or "manual" — show a Flag button to log inputs/outputs
flagging_dir .gradio/flagged Where flagged data (CSV) is stored
submit_btn / clear_btn / stop_btn text/Button Customize the action buttons (string label or gr.Button)
additional_inputs None Extra inputs rendered in a collapsible accordion
concurrency_limit "default" Max simultaneous runs of this event
batch / max_batch_size False / 4 Process inputs in batches (function must accept/return lists)
show_progress "full" "full", "minimal", or "hidden" progress animation
api_name / api_visibility None / "public" Control how this appears in the REST API

Tip

additional_inputs is the clean way to add optional knobs (temperature, max-tokens, etc.) without cluttering the main UI — they appear in a collapsed accordion below the primary inputs.

4.7 From a Hugging Face pipeline

If you have a transformers or diffusers pipeline, Gradio infers the inputs and outputs for you:

import gradio as gr
from transformers import pipeline

pipe = pipeline("image-classification")
gr.Interface.from_pipeline(pipe).launch()

4.8 Tabbed interfaces

Combine several Interfaces (or Blocks) into one tabbed app:

gr.TabbedInterface(
    [demo1, demo2],
    tab_names=["Classifier", "Generator"],
).launch()

5. Building with gr.Blocks

gr.Blocks is Gradio's low-level API. You create a Blocks object, enter it as a context manager (with), declare components and layouts inside, and wire up events. You still write only Python.

5.1 The basic pattern

import gradio as gr

def update(name):
    return f"Welcome to Gradio, {name}!"

with gr.Blocks() as demo:
    gr.Markdown("Start typing below and then click **Run**.")
    with gr.Row():
        inp = gr.Textbox(placeholder="What is your name?")
        out = gr.Textbox()
    btn = gr.Button("Run")
    btn.click(fn=update, inputs=inp, outputs=out)

demo.launch()

Three things happen here:

  1. Components (gr.Markdown, gr.Textbox, gr.Button) are declared in the order they should appear.
  2. Layout blocks (gr.Row) control arrangement.
  3. Event listeners (btn.click(...)) connect a user action to a function.

5.2 Layout components

Nest these as context managers to arrange your UI:

Layout Effect
gr.Row() Place children side by side horizontally
gr.Column() Stack children vertically (use scale= for relative width)
gr.Tabs() / gr.Tab() Tabbed sections
gr.Accordion(label, open=False) Collapsible section
gr.Group() Visually group components with no padding between them
gr.Sidebar() A collapsible side panel
gr.Walkthrough() / gr.Step() Multi-step guided flow
gr.Draggable() Drag-to-reorder container
with gr.Blocks() as demo:
    with gr.Row():
        with gr.Column(scale=2):
            inp = gr.Textbox(label="Input")
        with gr.Column(scale=1):
            out = gr.Label(label="Output")
    with gr.Accordion("Advanced settings", open=False):
        temp = gr.Slider(0, 1, label="Temperature")

5.3 Outputs feeding inputs

Unlike Interface, Blocks lets any output drive any other function — build chains and graphs of computation:

with gr.Blocks() as demo:
    text = gr.Textbox()
    upper = gr.Textbox()
    reversed_ = gr.Textbox()
    text.change(lambda s: s.upper(), text, upper)
    upper.change(lambda s: s[::-1], upper, reversed_)

5.4 Updating component properties

Return a re-instantiated component (or gr.update(...)) to change properties — value, visibility, label, interactivity — at runtime:

def toggle(show):
    return gr.Textbox(visible=show)

with gr.Blocks() as demo:
    check = gr.Checkbox(label="Show box")
    box = gr.Textbox(visible=False)
    check.change(toggle, check, box)

Tip

gr.update(value=..., visible=..., interactive=...) is a lightweight alternative when you only want to change a few properties without re-creating the component.

5.5 Multi-page apps

Use demo.route("Page Name", "/path") to add additional pages to a single Blocks app, and gr.Navbar to navigate between them.


6. The Component Library

Gradio includes 40+ built-in components. Each works as an input, an output, or both, and each has rich, type-aware preprocessing/postprocessing so your Python function receives convenient native types (a str, a numpy array, a PIL.Image, a pandas.DataFrame, …).

6.1 Text & number components

Component String shortcut Python type
gr.Textbox "text" / "textbox" str
gr.TextArea "textarea" str (multi-line)
gr.Number "number" float / int
gr.Slider "slider" float
gr.Checkbox "checkbox" bool
gr.CheckboxGroup "checkboxgroup" list[str]
gr.Radio "radio" str
gr.Dropdown "dropdown" str / list
gr.ColorPicker "colorpicker" str (hex)
gr.DateTime — str / timestamp
gr.Code "code" str (syntax-highlighted)

6.2 Media components

Component Python type Notes
gr.Image numpy.ndarray / PIL.Image / filepath type= controls the format
gr.ImageEditor dict of layers Draw, crop, mask, inpaint
gr.ImageSlider tuple of two images Before/after comparison
gr.Audio (sample_rate, numpy) / filepath Recording + playback
gr.Video filepath Upload, record, playback
gr.Gallery list of images Grid of images
gr.Model3D filepath 3D model viewer
gr.File / gr.FileExplorer filepath(s) Upload / browse files

6.3 Structured-data & plotting components

Component Python type Notes
gr.Dataframe pandas.DataFrame Editable table
gr.JSON dict / list Pretty-printed JSON
gr.Label dict[str, float] Classification scores
gr.HighlightedText list of (text, label) Token/NER highlighting
gr.BarPlot / gr.LinePlot / gr.ScatterPlot pandas.DataFrame Native charts
gr.Plot matplotlib/plotly/bokeh figure Embed any plotting library

6.4 Chat, display & control components

Component Purpose
gr.Chatbot Renders a conversation (used by ChatInterface)
gr.MultimodalTextbox Text input + file attachments
gr.Dialogue Multi-speaker dialogue editor
gr.Markdown / gr.HTML Static rich text / raw HTML
gr.Button Trigger an event
gr.UploadButton / gr.DownloadButton File upload / download buttons
gr.ClearButton / gr.DuplicateButton / gr.LoginButton / gr.DeepLinkButton Specialized action buttons
gr.State / gr.BrowserState Hidden session state (server / browser-persisted)
gr.Timer Fire an event on an interval
gr.Navbar Page navigation bar
gr.WorkflowCanvas Visual node-based workflow editor

Note

Session state: gr.State() holds a per-session Python object that persists across interactions but is not displayed. gr.BrowserState() persists data in the user's browser local storage across page reloads. Use them to keep conversation history, counters, or user-specific data.

6.5 Common component parameters

Most components share these constructor arguments:

Parameter Purpose
value Initial value (or a function to compute it)
label Text label shown above the component
info Extra helper text below the label
visible Show or hide the component
interactive Whether users can edit it (inputs are interactive, outputs are not, by default)
elem_id / elem_classes DOM id/classes for custom CSS targeting
scale / min_width Relative sizing within a Row/Column
render If False, defer rendering (declare now, place later)

7. Event Listeners

In Blocks, components expose event listener methods. Calling one wires a user action to a function. The signature is consistent:

component.event(fn, inputs, outputs, **kwargs)

7.1 The event catalog

Event Fires when…
.click() A button/component is clicked
.change() A value changes (by user or function)
.input() A value changes by the user only
.submit() Enter is pressed in a textbox
.select() An item/region is selected
.upload() A file is uploaded
.clear() A component is cleared
.stream() Streaming input (webcam/mic) produces a chunk
.key_up() A key is released (live search)
.focus() / .blur() Component gains/loses focus
.play() / .pause() / .stop() / .end() Media playback events
.start_recording() / .stop_recording() Audio/video recording events
.like() / .retry() / .undo() / .edit() Chatbot interactions
.delete() / .download() / .copy() File/clipboard actions
.expand() / .collapse() Accordion toggled
.tick() A gr.Timer interval elapses
.load() The app (or a component value) first loads

7.2 Chaining events with .then() and .success()

Every event listener returns a dependency you can chain:

click_event = btn.click(step_one, inp, mid)
click_event.then(step_two, mid, out)            # runs after, regardless of success
click_event.success(step_three, mid, log)        # runs only if step_one succeeded

7.3 Triggering on multiple events with gr.on

gr.on(
    triggers=[textbox.submit, button.click],
    fn=respond,
    inputs=textbox,
    outputs=output,
)

7.4 Streaming and progress

Make fn a generator (yield) to stream partial results to the UI. Add a gr.Progress() argument to report progress bars:

def generate(prompt, progress=gr.Progress()):
    for i in progress.tqdm(range(10)):
        ...
        yield partial_result

Important

Generator functions (those that yield) require the queue to be enabled. The queue is on by default, so this usually works automatically — but if you call .queue(...) you must do so before .launch().


8. Building Chatbots with gr.ChatInterface

gr.ChatInterface builds a complete chatbot UI from a single message-handling function. Only fn is required.

8.1 The chat function contract

Your function receives message (the user's latest input as a str) and history (a list of OpenAI-style {"role": ..., "content": ...} dicts). It returns or yields the assistant's reply:

import gradio as gr

def echo(message, history):
    return f"You said: {message}"

gr.ChatInterface(fn=echo, title="Echo Bot").launch()

8.2 Streaming responses

Yield progressively to stream tokens as they are produced:

def slow_echo(message, history):
    response = ""
    for char in message:
        response += char
        yield response

gr.ChatInterface(fn=slow_echo).launch()

8.3 Connecting a real LLM

from openai import OpenAI
client = OpenAI()

def chat(message, history):
    messages = history + [{"role": "user", "content": message}]
    stream = client.chat.completions.create(
        model="gpt-4o-mini", messages=messages, stream=True
    )
    response = ""
    for chunk in stream:
        response += chunk.choices[0].delta.content or ""
        yield response

gr.ChatInterface(fn=chat, type="messages").launch()

8.4 Multimodal & advanced chat features

Parameter Effect
multimodal=True Use a MultimodalTextbox so users can attach files; message becomes {"text": ..., "files": [...]}
editable=True Users can edit past messages and regenerate
save_history=True Persist conversations to the browser and show a history side panel
examples=[...] Clickable starter prompts (strings, or dicts with text/files)
additional_inputs=[...] Extra controls (system prompt, temperature) passed after history
additional_outputs=[...] Update other components (e.g. an artifact panel) from the chat function
flagging_mode="manual" Show 👍/👎 feedback on assistant messages (flagging_options=("Like","Dislike"))

Tip

Set type="messages" to use the modern OpenAI-style dictionary history format. This is the recommended format for new chatbots.


9. Launching & Sharing Your App

.launch() starts the web server. It returns (app, local_url, share_url).

9.1 Common launch options

Parameter Default Purpose
share False Create a temporary public *.gradio.live link
server_name "127.0.0.1" Set to "0.0.0.0" to expose on your local network
server_port 7860 (auto-search) Port to bind
auth None Require login (see Authentication)
inbrowser False Auto-open a browser tab
debug False Block the main thread and print errors (needed in Colab)
show_error False Show full errors in the UI and browser console
favicon_path None Custom favicon (.png/.gif/.ico)
max_file_size None Cap uploads, e.g. "5mb"
pwa None Make the app installable as a Progressive Web App
ssr_mode False Server-side rendering (needs Node 20+) for performance/SEO

9.2 Styling at launch

Important

Changed in Gradio 6.0: theme, css, css_paths, js, head, and head_paths moved from the gr.Blocks(...) constructor to .launch(...). Passing them to the constructor now emits a warning. Update older code accordingly.

demo.launch(
    theme="soft",
    css=".gradio-container {background: #f0f0f0}",
)

See Themes & Styling.

9.3 Custom HTTPS

demo.launch(
    ssl_keyfile="key.pem",
    ssl_certfile="cert.pem",
)

9.4 Mounting inside an existing FastAPI app

from fastapi import FastAPI
import gradio as gr

app = FastAPI()

@app.get("/")
def root():
    return {"message": "Hello"}

app = gr.mount_gradio_app(app, demo, path="/gradio")

10. The Queue & Concurrency

The queue manages how many function calls run at once and gives users their position while waiting. It is enabled by default.

demo.queue(
    max_size=20,                      # max events held; new ones rejected when full
    default_concurrency_limit=2,      # default simultaneous runs per event
)
demo.launch()
queue() parameter Default Purpose
max_size None (unlimited) Maximum events in the queue
default_concurrency_limit 1 Default concurrency_limit for events that don't set one
status_update_rate "auto" How often queue positions are broadcast
api_open — If True, REST routes bypass the queue

Set per-event limits with concurrency_limit= on .click()/.then()/etc., and group events that share a resource with the same concurrency_id.

Note

The environment variable GRADIO_DEFAULT_CONCURRENCY_LIMIT sets the default concurrency limit globally without editing code.


11. Hot Reload & Vibe Mode — the gradio CLI

Installing Gradio adds a gradio command-line tool.

11.1 Hot reload

Run your app with gradio instead of python to auto-reload on every file change:

gradio app.py

If your Blocks/Interface object is named something other than demo, pass the name:

gradio app.py my_app

11.2 Vibe mode — edit your app in natural language

gradio --vibe app.py

This opens an in-browser chat panel that can write or edit your Gradio app from natural-language instructions.

Caution

Vibe mode lets anyone who can reach the app endpoint modify files and run arbitrary code on the host machine. Use it only locally, never on a public or production server.

11.3 The full CLI

Command Purpose
gradio app.py Run in hot-reload mode (default)
gradio --vibe [app.py] Hot reload + in-browser natural-language editor
gradio deploy Deploy the current directory to Hugging Face Spaces or Google Cloud Run
gradio sketch Visually design a Gradio app
gradio environment Print Gradio environment info (for bug reports)
gradio info Print the JSON payload schema for an app's endpoints
gradio predict Send a prediction request to an app endpoint
gradio load <space> Load and run a remote Space locally
gradio skills add ... Install AI coding skills
gradio cc <build|dev|create|show|publish|install> Custom-component development

12. Querying Apps Programmatically

Every Gradio app is also an API. Any event with an api_name is exposed as a REST endpoint, and Gradio generates client libraries for it.

12.1 View the API

Click the "Use via API" link in your app's footer, or visit http://localhost:7860/?view=api, to see auto-generated docs with copy-paste snippets for Python, JavaScript, and cURL.

12.2 The Python client

pip install gradio_client
from gradio_client import Client

client = Client("http://127.0.0.1:7860/")   # or "username/space-name" on Spaces
result = client.predict("Alice", 3, api_name="/predict")
print(result)
Method Purpose
client.predict(*args, api_name=...) Call an endpoint and block for the result
client.submit(*args, api_name=...) Call asynchronously; returns a Job future
client.view_api() Print all endpoints and their signatures
client.duplicate(...) Duplicate a Space and connect to your copy

For file inputs, wrap paths with handle_file():

from gradio_client import Client, handle_file
client.predict(handle_file("cat.png"), api_name="/classify")

12.3 The JavaScript client

npm install @gradio/client
import { Client } from "@gradio/client";

const client = await Client.connect("username/space-name");
const result = await client.predict("/predict", ["Alice", 3]);
console.log(result.data);

12.4 Controlling API visibility

Set api_visibility on any event:

Value Shown in API docs? Callable by clients?
"public" (default) Yes Yes
"undocumented" No Yes
"private" No No

13. Examples & Caching

Provide examples so users can try your app with one click. Cache them to display results instantly.

gr.Interface(
    fn=classify,
    inputs=gr.Image(),
    outputs=gr.Label(),
    examples=["cat.png", "dog.png"],
    cache_examples=True,      # pre-compute outputs at launch
    cache_mode="eager",       # or "lazy" (compute on first use)
)
Option Effect
cache_examples=True Pre-run examples so clicking shows the cached output instantly
cache_mode="eager" Compute all examples at launch
cache_mode="lazy" Compute each example the first time any user clicks it
examples_per_page How many examples to show per page

Note

On Hugging Face Spaces, cache_examples defaults to True. The GRADIO_CACHE_EXAMPLES and GRADIO_CACHE_MODE environment variables override the defaults.


14. Gradio as an MCP Server

Gradio apps can act as Model Context Protocol (MCP) servers, exposing your documented functions as tools that AI agents (Claude, Cursor, etc.) can call.

import gradio as gr

def letter_counter(word: str, letter: str) -> int:
    """Count occurrences of a letter in a word."""
    return word.lower().count(letter.lower())

demo = gr.Interface(fn=letter_counter, inputs=["text", "text"], outputs="number")
demo.launch(mcp_server=True)

With mcp_server=True, every public, documented function becomes an MCP tool. The MCP endpoint and a landing page are served automatically.

Tip

Install the MCP extra first: pip install "gradio[mcp]". You can also enable MCP without code by setting GRADIO_MCP_SERVER=True.

For fine-grained control, Server mode (gr.Server) lets you register MCP tools, resources, and prompts with decorators alongside ordinary FastAPI routes — see the Admin Guide.


15. Authentication

15.1 Username/password

demo.launch(auth=("admin", "secret"))                       # single user
demo.launch(auth=[("alice", "pw1"), ("bob", "pw2")])         # multiple users

Or pass a function for custom logic:

def check(username, password):
    return username == "admin" and verify(password)

demo.launch(auth=check, auth_message="Please sign in.")

15.2 OAuth / external auth

Use auth_dependency (a function taking a FastAPI request and returning a user id or None) to integrate OAuth and other external systems. Add a gr.LoginButton for Hugging Face sign-in. The [oauth] extra is required.

Warning

auth and auth_dependency are mutually exclusive — pass only one to .launch().


16. Themes & Styling

16.1 Built-in themes

demo.launch(theme="soft")    # "default", "soft", "monochrome", "glass", "origin", "citrus", "ocean"

You can also load community themes from the Hub: theme="gradio/seafoam".

16.2 Custom CSS

demo.launch(
    css=".gradio-container {max-width: 800px !important}",
)

Target individual components with elem_id / elem_classes and matching CSS selectors. Use css_paths to load CSS from a file.

16.3 Building a theme

gr.themes.Base (and Soft, Monochrome, etc.) can be subclassed and tweaked. Build interactively with the theme builder:

import gradio as gr
gr.themes.builder()

17. Deploying to Hugging Face Spaces

The easiest permanent host is a free Hugging Face Space:

gradio deploy

Run this inside your app's directory; the CLI prompts for a Space name and uploads your files. Alternatively, create a Space on huggingface.co, choose the Gradio SDK, and push an app.py plus a requirements.txt.

Tip

On Spaces, Gradio automatically enables example caching, a "Duplicate this Space" button (when allow_duplication=True), and Progressive Web App support.

gradio deploy can also target Google Cloud Run.


18. AI Coding Skills

Gradio ships a "skill" that teaches AI coding assistants (Cursor, Claude Code, Codex, OpenCode) how to build Gradio apps correctly — especially custom components and styling:

gradio skills add --cursor      # or --claude, --codex, --opencode

Add --global to install for all projects. You can also generate API-usage docs for a specific Space:

gradio skills add abidlabs/en2fr --cursor

19. Custom Components

Build and publish your own reusable component (Python backend + Svelte frontend) with the gradio cc toolchain:

Command Purpose
gradio cc create <Name> Scaffold a new custom component
gradio cc dev Run the component's dev server with hot reload
gradio cc build Build the component for distribution
gradio cc show List installed custom components
gradio cc publish Publish to PyPI and the Hugging Face gallery
gradio cc install Install a custom component's dependencies

20. Troubleshooting

Cause: You are in an environment (e.g. Google Colab, some containers) where localhost is not reachable. Solution: Call demo.launch(share=True). Prevention: In notebooks/Colab, always launch with share=True.

Error: Queue needs to be enabled!

Cause: You used a generator (yield) function, or an event that cancels another, without the queue enabled. Solution: The queue is on by default; if you disabled it, call demo.queue() before demo.launch(). Prevention: Don't pass api_open/queue settings that disable queuing for streaming apps.

Error: inputs must be a string, list, or Component

Cause: Something other than a component (or its string shortcut) was passed to inputs/outputs. Solution: Pass gr.Textbox() (or "text"), not a raw value or unrelated object. Prevention: Remember inputs/outputs take components, while value= takes data.

Problem: The number of inputs doesn't match my function

Cause: The count of inputs components must equal the number of fn parameters (and outputs the number of return values). Solution: Add/remove components so the counts line up, or use additional_inputs for optional ones.

Problem: My app runs but isn't reachable from another machine

Cause: By default Gradio binds to 127.0.0.1 (localhost only). Solution: demo.launch(server_name="0.0.0.0") (or set GRADIO_SERVER_NAME=0.0.0.0). Prevention: Only expose 0.0.0.0 on trusted networks, and add auth= if needed.

Problem: A local file (image/CSV) won't display or download

Cause: Gradio only serves files inside its working/cache directories by default for security. Solution: Add the file's directory to allowed_paths=[...] in .launch() (or GRADIO_ALLOWED_PATHS). Prevention: Keep user-served assets under the app directory; use allowed_paths deliberately.

Error: Cannot find empty port in range

Cause: Ports 7860–7959 are all occupied. Solution: Free a port or set server_port= / GRADIO_SERVER_PORT to an open one.

Problem: Custom theme/CSS passed to gr.Blocks() is ignored (Gradio 6)

Cause: In Gradio 6.0 these moved to .launch(). Solution: Pass theme=, css=, js=, head= to demo.launch(...) instead of gr.Blocks(...).

Problem: SSR mode warning or failure

Cause: ssr_mode=True requires Node.js 20+ on the host. Solution: Install Node 20+, or set ssr_mode=False (the default).

Problem: gr.Dataframe freezes inside a Tab after upgrading

Cause: Known issue (#13448) on certain 6.x versions. Solution: Upgrade to the latest patch release; track the issue for fixes.

Problem: Telemetry / version-check network calls at startup

Cause: Gradio performs anonymous analytics and a version check by default. Solution: Set analytics_enabled=False (constructor) or GRADIO_ANALYTICS_ENABLED=False.


21. Frequently Asked Questions

Q: Do I need to know JavaScript, HTML, or CSS to use Gradio? No. Everything — layout, interactivity, events — is written in Python. CSS/JS are optional escape hatches for advanced styling.

Q: When should I use Interface vs Blocks? Use Interface to wrap a single function with fixed inputs/outputs. Use Blocks when you need custom layouts, multiple interacting functions, or dynamic UIs. Use ChatInterface for chatbots.

Q: How do I stream output token-by-token? Make fn a generator and yield partial results. The queue (on by default) handles streaming.

Q: Is the share link permanent? No — share=True links last about 72 hours and tunnel from your machine. For permanent hosting, deploy to Hugging Face Spaces with gradio deploy.

Q: How do I keep per-user data between interactions? Use gr.State() for in-memory session state, or gr.BrowserState() to persist in the browser across reloads.

Q: Can other programs call my Gradio app? Yes. Every app exposes a REST API. Use gradio_client (Python) or @gradio/client (JS), or visit /?view=api for snippets.

Q: How do I add a temperature/system-prompt knob to a chatbot? Pass additional_inputs=[...] to gr.ChatInterface; the values are appended to your function's arguments after history.

Q: How do I let an AI agent call my function? Launch with mcp_server=True (and pip install "gradio[mcp]"). Documented functions become MCP tools.

Q: How do I run my app for development with auto-reload? Run gradio app.py instead of python app.py.

Q: How do I limit how many people run my model at once? Set concurrency_limit= on the event (or default_concurrency_limit in .queue()), and cap the queue with max_size.

Q: How do I require a login? Pass auth=("user", "password") (or a list, or a function) to .launch().

Q: Why does my function receive a numpy array / PIL image / DataFrame instead of a file path? Each component preprocesses its value into a convenient Python type. Configure the format with the component's type= argument (e.g. gr.Image(type="filepath")).

Q: Can I embed a Gradio app in my own website? Yes — use the auto-generated Web Component / iframe embed code shown on a Space, or mount it in your FastAPI app with gr.mount_gradio_app.


22. Quick Reference

Minimal apps

# Interface
gr.Interface(fn, inputs, outputs).launch()

# Blocks
with gr.Blocks() as demo:
    inp = gr.Textbox(); out = gr.Textbox(); btn = gr.Button("Go")
    btn.click(fn, inp, out)
demo.launch()

# ChatInterface
gr.ChatInterface(fn).launch()

Launch cheat-sheet

Goal Code
Public link demo.launch(share=True)
LAN access demo.launch(server_name="0.0.0.0")
Require login demo.launch(auth=("user","pw"))
Choose port demo.launch(server_port=8080)
MCP server demo.launch(mcp_server=True)
Apply theme demo.launch(theme="soft")
Cap uploads demo.launch(max_file_size="5mb")

Key environment variables

Variable Default Effect
GRADIO_SERVER_NAME 127.0.0.1 Bind address
GRADIO_SERVER_PORT 7860 Port
GRADIO_SHARE False Force a share link
GRADIO_ANALYTICS_ENABLED True Anonymous telemetry
GRADIO_TEMP_DIR system tmp Where Gradio caches files
GRADIO_ALLOWED_PATHS / GRADIO_BLOCKED_PATHS — Extra/forbidden served paths
GRADIO_MCP_SERVER False Enable MCP server
GRADIO_SSR_MODE False Server-side rendering

The gradio CLI

Command Purpose
gradio app.py Hot-reload dev server
gradio --vibe app.py Natural-language editor (local only ⚠️)
gradio deploy Deploy to Spaces / Cloud Run
gradio sketch Visual app designer
gradio cc ... Custom component toolchain
gradio environment Print env info
gradio skills add Install AI coding skills