Gradio

gradio.app
AI & Machine Learning

Build & Share Delightful Machine Learning Apps

llms.txt

This page contains the documentation for the Gradio library. It is organized into the following sections:

  • Gradio 6 Migration Guide
  • Quickstart
  • The Interface Class
  • Blocks And Event Listeners
  • Controlling Layout
  • More Blocks Features
  • Custom Css And Js
  • Streaming Outputs
  • Streaming Inputs
  • API Reference: This section contains all the class and function signatures in the Gradio library.
  • End to End Demos: This section contains examples of full end-to-end Gradio apps.

Gradio 6 Migration Guide

We are excited to release Gradio 6, the latest major version of the Gradio library. Gradio 6 is significantly more performant, lighter, and easier to customize than previous versions of Gradio. The Gradio team is only planning on maintaining future versions of Gradio 6 so we encourage all developers to migrate to Gradio 6.x.

Gradio 6 includes several breaking changes that were made in order to standardize the Python API. This migration guide lists the breaking changes and the specific code changes needed in order to migrate. The easiest way to know whether you need to make changes is to upgrade your Gradio app to 5.50 (pip install --upgrade gradio==5.50). Gradio 5.50 emits deprecation warnings for any parameters removed in Gradio 6, allowing you to know whether your Gradio app will be compatible with Gradio 6.

Here, we walk through the breaking changes that were introduced in Gradio 6. Code snippets are provided, allowing you to migrate your code easily to Gradio 6. You can also copy-paste this document as Markdown if you are using an LLM to help migrate your code.

App-level Changes

App-level parameters have been moved from Blocks to launch()

The gr.Blocks class constructor previously contained several parameters that applied to your entire Gradio app, specifically:

  • theme: The theme for your Gradio app
  • css: Custom CSS code as a string
  • css_paths: Paths to custom CSS files
  • js: Custom JavaScript code
  • head: Custom HTML code to insert in the head of the page
  • head_paths: Paths to custom HTML files to insert in the head

Since gr.Blocks can be nested and are not necessarily unique to a Gradio app, these parameters have now been moved to Blocks.launch(), which can only be called once for your entire Gradio app.

Before (Gradio 5.x):

import gradio as gr

with gr.Blocks(
    theme=gr.themes.Soft(),
    css=".my-class { color: red; }",
) as demo:
    gr.Textbox(label="Input")

demo.launch()

After (Gradio 6.x):

import gradio as gr

with gr.Blocks() as demo:
    gr.Textbox(label="Input")

demo.launch(
    theme=gr.themes.Soft(),
    css=".my-class { color: red; }",
)

This change makes it clearer that these parameters apply to the entire app and not to individual Blocks instances.

show_api parameter replaced with footer_links

The show_api parameter in launch() has been replaced with a more flexible footer_links parameter that allows you to control which links appear in the footer of your Gradio app.

In Gradio 5.x:

  • show_api=True (default) showed the API documentation link in the footer
  • show_api=False hid the API documentation link

In Gradio 6.x:

  • footer_links accepts a list of strings: ["api", "gradio", "settings"]
  • You can now control precisely which footer links are shown:
    • "api": Shows the API documentation link
    • "gradio": Shows the "Built with Gradio" link
    • "settings": Shows the settings link

Before (Gradio 5.x):

import gradio as gr

with gr.Blocks() as demo:
    gr.Textbox(label="Input")

demo.launch(show_api=False)

After (Gradio 6.x):

import gradio as gr

with gr.Blocks() as demo:
    gr.Textbox(label="Input")

demo.launch(footer_links=["gradio", "settings"])

To replicate the old behavior:

  • show_api=Truefooter_links=["api", "gradio", "settings"] (or just omit the parameter, as this is the default)
  • show_api=Falsefooter_links=["gradio", "settings"]

Event listener parameters: show_api removed and api_name=False no longer supported

In event listeners (such as .click(), .change(), etc.), the show_api parameter has been removed, and api_name no longer accepts False as a valid value. These have been replaced with a new api_visibility parameter that provides more fine-grained control.

In Gradio 5.x:

  • show_api=True (default) showed the endpoint in the API documentation
  • show_api=False hid the endpoint from API docs but still allowed downstream apps to use it
  • api_name=False completely disabled the API endpoint (no downstream apps could use it)

In Gradio 6.x:

  • api_visibility accepts one of three string values:
    • "public": The endpoint is shown in API docs and accessible to all (equivalent to old show_api=True)
    • "undocumented": The endpoint is hidden from API docs but still accessible to downstream apps (equivalent to old show_api=False)
    • "private": The endpoint is hidden from API docs and not callable by the Gradio client libraries (equivalent to old api_name=False). Note: direct HTTP requests to the endpoint are still possible.

Before (Gradio 5.x):

import gradio as gr

with gr.Blocks() as demo:
    btn = gr.Button("Click me")
    output = gr.Textbox()
    
    btn.click(fn=lambda: "Hello", outputs=output, show_api=False)
    
demo.launch()

Or to completely disable the API:

btn.click(fn=lambda: "Hello", outputs=output, api_name=False)

After (Gradio 6.x):

import gradio as gr

with gr.Blocks() as demo:
    btn = gr.Button("Click me")
    output = gr.Textbox()
    
    btn.click(fn=lambda: "Hello", outputs=output, api_visibility="undocumented")
    
demo.launch()

Or to completely disable the API:

btn.click(fn=lambda: "Hello", outputs=output, api_visibility="private")

To replicate the old behavior:

  • show_api=Trueapi_visibility="public" (or just omit the parameter, as this is the default)
  • show_api=Falseapi_visibility="undocumented"
  • api_name=Falseapi_visibility="private"

like_user_message moved from .like() event to constructor

The like_user_message parameter has been moved from the .like() event listener to the Chatbot constructor.

Before (Gradio 5.x):

chatbot = gr.Chatbot()
chatbot.like(print_like_dislike, None, None, like_user_message=True)

After (Gradio 6.x):

chatbot = gr.Chatbot(like_user_message=True)
chatbot.like(print_like_dislike, None, None)

Default API names for Interface and ChatInterface now use function names

The default API endpoint names for gr.Interface and gr.ChatInterface have changed to be consistent with how gr.Blocks events work and to better support MCP (Model Context Protocol) tools.

In Gradio 5.x:

  • gr.Interface had a default API name of /predict
  • gr.ChatInterface had a default API name of /chat

In Gradio 6.x:

  • Both gr.Interface and gr.ChatInterface now use the name of the function you pass in as the default API endpoint name
  • This makes the API more descriptive and consistent with gr.Blocks behavior

E.g. if your Gradio app is:

import gradio as gr

def generate_text(prompt):
    return f"Generated: {prompt}"

demo = gr.Interface(fn=generate_text, inputs="text", outputs="text")
demo.launch()

Previously, the API endpoint that Gradio generated would be: /predict. Now, the API endpoint will be: /generate_text

To maintain the old endpoint names:

If you need to keep the old endpoint names for backward compatibility (e.g., if you have external services calling these endpoints), you can explicitly set the api_name parameter:

demo = gr.Interface(fn=generate_text, inputs="text", outputs="text", api_name="predict")

Similarly for ChatInterface:

demo = gr.ChatInterface(fn=chat_function, api_name="chat")

gr.Chatbot and gr.ChatInterface tuple format removed

The tuple format for chatbot messages has been removed in Gradio 6.0. You must now use the messages format with dictionaries containing "role" and "content" keys.

In Gradio 5.x:

  • You could use type="tuples" or the default tuple format: [["user message", "assistant message"], ...]
  • The tuple format was a list of lists where each inner list had two elements: [user_message, assistant_message]

In Gradio 6.x:

  • Only the messages format is supported: type="messages"
  • Messages must be dictionaries with "role" and "content" keys: [{"role": "user", "content": "Hello"}, {"role": "assistant", "content": "Hi there!"}]

Before (Gradio 5.x):

import gradio as gr

# Using tuple format
chatbot = gr.Chatbot(value=[["Hello", "Hi there!"]])

Or with type="tuples":

chatbot = gr.Chatbot(value=[["Hello", "Hi there!"]], type="tuples")

After (Gradio 6.x):

import gradio as gr

# Must use messages format
chatbot = gr.Chatbot(
    value=[
        {"role": "user", "content": "Hello"},
        {"role": "assistant", "content": "Hi there!"}
    ],
    type="messages"
)

Similarly for gr.ChatInterface, if you were manually setting the chat history:

# Before (Gradio 5.x)
demo = gr.ChatInterface(
    fn=chat_function,
    examples=[["Hello", "Hi there!"]]
)

# After (Gradio 6.x)
demo = gr.ChatInterface(
    fn=chat_function,
    examples=[{"role": "user", "content": "Hello"}, {"role": "assistant", "content": "Hi there!"}]
)

Note: If you're using gr.ChatInterface with a function that returns messages, the function should return messages in the new format. The tuple format is no longer supported.

gr.ChatInterface history format now uses structured content

The history format in gr.ChatInterface has been updated to consistently use OpenAI-style structured content format. Content is now always a list of content blocks, even for simple text messages.

In Gradio 5.x:

  • Content could be a simple string: {"role": "user", "content": "Hello"}
  • Simple text messages used a string directly

In Gradio 6.x:

  • Content is always a list of content blocks: {"role": "user", "content": [{"type": "text", "text": "Hello"}]}
  • This format is consistent with OpenAI's message format and supports multimodal content (text, images, etc.)

Before (Gradio 5.x):

history = [
    {"role": "user", "content": "What is the capital of France?"},
    {"role": "assistant", "content": "Paris"}
]

After (Gradio 6.x):

history = [
    {"role": "user", "content": [{"type": "text", "text": "What is the capital of France?"}]},
    {"role": "assistant", "content": [{"type": "text", "text": "Paris"}]}
]

With files:

When files are uploaded in the chat, they are represented as content blocks with "type": "file". All content blocks (files and text) are grouped together in the same message's content array:

history = [
    {
        "role": "user",
        "content": [
            {"type": "file", "file": {"path": "cat1.png"}},
            {"type": "file", "file": {"path": "cat2.png"}},
            {"type": "text", "text": "What's the difference between these two images?"}
        ]
    }
]

This structured format allows for multimodal content (text, images, files, etc.) in chat messages, making it consistent with OpenAI's API format. All files uploaded in a single message are grouped together in the content array along with any text content.

cache_examples parameter updated and cache_mode introduced

The cache_examples parameter (used in Interface, ChatInterface, and Examples) no longer accepts the string value "lazy". It now strictly accepts boolean values (True or False). To control the caching strategy, a new cache_mode parameter has been introduced.

In Gradio 5.x:

  • cache_examples accepted True, False, or "lazy".

In Gradio 6.x:

  • cache_examples only accepts True or False.
  • cache_mode accepts "eager" (default) or "lazy".

Before (Gradio 5.x):

import gradio as gr

demo = gr.Interface(
    fn=predict, 
    inputs="text", 
    outputs="text", 
    examples=["Hello", "World"],
    cache_examples="lazy"
)

After (Gradio 6.x):

You must now set cache_examples=True and specify the mode separately:

import gradio as gr

demo = gr.Interface(
    fn=predict, 
    inputs="text", 
    outputs="text", 
    examples=["Hello", "World"],
    cache_examples=True,
    cache_mode="lazy"
)

If you previously used cache_examples=True (which implied eager caching), no changes are required, as cache_mode defaults to "eager".

Component-level Changes

gr.Video no longer accepts tuple values for video and subtitles

The tuple format for returning video with subtitles has been deprecated. Instead of returning a tuple (video_path, subtitle_path), you should now use the gr.Video component directly with the subtitles parameter.

In Gradio 5.x:

  • You could return a tuple of (video_path, subtitle_path) from a function
  • The tuple format was (str | Path, str | Path | None)

In Gradio 6.x:

  • Return a gr.Video component instance with the subtitles parameter
  • This provides more flexibility and consistency with other components

Before (Gradio 5.x):

import gradio as gr

def generate_video_with_subtitles(input):
    video_path = "output.mp4"
    subtitle_path = "subtitles.srt"
    return (video_path, subtitle_path)

demo = gr.Interface(
    fn=generate_video_with_subtitles,
    inputs="text",
    outputs=gr.Video()
)
demo.launch()

After (Gradio 6.x):

import gradio as gr

def generate_video_with_subtitles(input):
    video_path = "output.mp4"
    subtitle_path = "subtitles.srt"
    return gr.Video(value=video_path, subtitles=subtitle_path)

demo = gr.Interface(
    fn=generate_video_with_subtitles,
    inputs="text",
    outputs=gr.Video()
)
demo.launch()

gr.HTML padding parameter default changed to False

The default value of the padding parameter in gr.HTML has been changed from True to False for consistency with gr.Markdown.

In Gradio 5.x:

  • padding=True was the default for gr.HTML
  • HTML components had padding by default

In Gradio 6.x:

  • padding=False is the default for gr.HTML
  • This matches the default behavior of gr.Markdown for consistency

To maintain the old behavior:

If you want to keep the padding that was present in Gradio 5.x, explicitly set padding=True:

html = gr.HTML("<div>Content</div>", padding=True)

gr.Dataframe row_count and col_count parameters restructured

The row_count and col_count parameters in gr.Dataframe have been restructured to provide more flexibility and clarity. The tuple format for specifying fixed/dynamic behavior has been replaced with separate parameters for initial counts and limits.

In Gradio 5.x:

  • row_count: int | tuple[int, str] - Could be an int or tuple like (5, "fixed") or (5, "dynamic")
  • col_count: int | tuple[int, str] | None - Could be an int or tuple like (3, "fixed") or (3, "dynamic")

In Gradio 6.x:

  • row_count: int | None - Just the initial number of rows to display
  • row_limits: tuple[int | None, int | None] | None - Tuple specifying (min_rows, max_rows) constraints
  • column_count: int | None - The initial number of columns to display
  • column_limits: tuple[int | None, int | None] | None - Tuple specifying (min_columns, max_columns) constraints

Before (Gradio 5.x):

import gradio as gr

# Fixed number of rows (users can't add/remove rows)
df = gr.Dataframe(row_count=(5, "fixed"), col_count=(3, "dynamic"))

Or with dynamic rows:

# Dynamic rows (users can add/remove rows)
df = gr.Dataframe(row_count=(5, "dynamic"), col_count=(3, "fixed"))

Or with just integers (defaults to dynamic):

df = gr.Dataframe(row_count=5, col_count=3)

After (Gradio 6.x):

import gradio as gr

# Fixed number of rows (users can't add/remove rows)
df = gr.Dataframe(row_count=5, row_limits=(5, 5), column_count=3, column_limits=None)

Or with dynamic rows (users can add/remove rows):

# Dynamic rows with no limits
df = gr.Dataframe(row_count=5, row_limits=None, column_count=3, column_limits=None)

Or with min/max constraints:

# Rows between 3 and 10, columns between 2 and 5
df = gr.Dataframe(row_count=5, row_limits=(3, 10), column_count=3, column_limits=(2, 5))

Migration examples:

  • row_count=(5, "fixed")row_count=5, row_limits=(5, 5)
  • row_count=(5, "dynamic")row_count=5, row_limits=None
  • row_count=5row_count=5, row_limits=None (same behavior)
  • col_count=(3, "fixed")column_count=3, column_limits=(3, 3)
  • col_count=(3, "dynamic")column_count=3, column_limits=None
  • col_count=3column_count=3, column_limits=None (same behavior)

allow_tags=True is now the default for gr.Chatbot

Due to the rise in LLMs returning HTML, markdown tags, and custom tags (such as <thinking> tags), the default value of allow_tags in gr.Chatbot has changed from False to True in Gradio 6.

In Gradio 5.x:

  • allow_tags=False was the default
  • All HTML and custom tags were sanitized/removed from chatbot messages (unless explicitly allowed)

In Gradio 6.x:

  • allow_tags=True is the default
  • All custom tags (non-standard HTML tags) are preserved in chatbot messages
  • Standard HTML tags are still sanitized for security unless sanitize_html=False

Before (Gradio 5.x):

import gradio as gr

chatbot = gr.Chatbot()

This would remove all tags from messages, including custom tags like <thinking>.

After (Gradio 6.x):

import gradio as gr

chatbot = gr.Chatbot()

This will now preserve custom tags like <thinking> in the messages.

To maintain the old behavior:

If you want to continue removing all tags from chatbot messages (the old default behavior), explicitly set allow_tags=False:

import gradio as gr

chatbot = gr.Chatbot(allow_tags=False)

Note: You can also specify a list of specific tags to allow:

chatbot = gr.Chatbot(allow_tags=["thinking", "tool_call"])

This will only preserve <thinking> and <tool_call> tags while removing all other custom tags.

Other removed component parameters

Several component parameters have been removed in Gradio 6.0. These parameters were previously deprecated and have now been fully removed.

gr.Chatbot removed parameters

bubble_full_width - This parameter has been removed as it no longer has any effect.

resizeable - This parameter (with the typo) has been removed. Use resizable instead.

Before (Gradio 5.x):

chatbot = gr.Chatbot(resizeable=True)

After (Gradio 6.x):

chatbot = gr.Chatbot(resizable=True)

show_copy_button, show_copy_all_button, show_share_button - These parameters have been removed. Use the buttons parameter instead.

Before (Gradio 5.x):

chatbot = gr.Chatbot(show_copy_button=True, show_copy_all_button=True, show_share_button=True)

After (Gradio 6.x):

chatbot = gr.Chatbot(buttons=["copy", "copy_all", "share"])

gr.Audio / WaveformOptions removed parameters

show_controls - This parameter in WaveformOptions has been removed. Use show_recording_waveform instead.

Before (Gradio 5.x):

audio = gr.Audio(
    waveform_options=gr.WaveformOptions(show_controls=False)
)

After (Gradio 6.x):

audio = gr.Audio(
    waveform_options=gr.WaveformOptions(show_recording_waveform=False)
)

min_length and max_length - These parameters have been removed. Use validators on event listeners instead.

Before (Gradio 5.x):

audio = gr.Audio(min_length=1, max_length=10)

After (Gradio 6.x):

audio = gr.Audio()

audio.upload(
    fn=process_audio,
    validator=lambda audio: gr.validators.is_audio_correct_length(audio, min_length=1, max_length=10),
    inputs=audio
)

show_download_button, show_share_button - These parameters have been removed. Use the buttons parameter instead.

Before (Gradio 5.x):

audio = gr.Audio(show_download_button=True, show_share_button=True)

After (Gradio 6.x):

audio = gr.Audio(buttons=["download", "share"])

Note: For components where show_share_button had a default of None (which would show the button on Spaces), you can use buttons=["share"] to always show it, or omit it from the list to hide it.

gr.Image removed parameters

mirror_webcam - This parameter has been removed. Use webcam_options with gr.WebcamOptions instead.

Before (Gradio 5.x):

image = gr.Image(mirror_webcam=True)

After (Gradio 6.x):

image = gr.Image(webcam_options=gr.WebcamOptions(mirror=True))

webcam_constraints - This parameter has been removed. Use webcam_options with gr.WebcamOptions instead.

Before (Gradio 5.x):

image = gr.Image(webcam_constraints={"facingMode": "user"})

After (Gradio 6.x):

image = gr.Image(webcam_options=gr.WebcamOptions(constraints={"facingMode": "user"}))

show_download_button, show_share_button, show_fullscreen_button - These parameters have been removed. Use the buttons parameter instead.

Before (Gradio 5.x):

image = gr.Image(show_download_button=True, show_share_button=True, show_fullscreen_button=True)

After (Gradio 6.x):

image = gr.Image(buttons=["download", "share", "fullscreen"])

gr.Video removed parameters

mirror_webcam - This parameter has been removed. Use webcam_options with gr.WebcamOptions instead.

Before (Gradio 5.x):

video = gr.Video(mirror_webcam=True)

After (Gradio 6.x):

video = gr.Video(webcam_options=gr.WebcamOptions(mirror=True))

webcam_constraints - This parameter has been removed. Use webcam_options with gr.WebcamOptions instead.

Before (Gradio 5.x):

video = gr.Video(webcam_constraints={"facingMode": "user"})

After (Gradio 6.x):

video = gr.Video(webcam_options=gr.WebcamOptions(constraints={"facingMode": "user"}))

min_length and max_length - These parameters have been removed. Use validators on event listeners instead.

Before (Gradio 5.x):

video = gr.Video(min_length=1, max_length=10)

After (Gradio 6.x):

video = gr.Video()

video.upload(
    fn=process_video,
    validator=lambda video: gr.validators.is_video_correct_length(video, min_length=1, max_length=10),
    inputs=video
)

show_download_button, show_share_button - These parameters have been removed. Use the buttons parameter instead.

Before (Gradio 5.x):

video = gr.Video(show_download_button=True, show_share_button=True)

After (Gradio 6.x):

video = gr.Video(buttons=["download", "share"])

gr.ImageEditor removed parameters

crop_size - This parameter has been removed. Use canvas_size instead.

Before (Gradio 5.x):

editor = gr.ImageEditor(crop_size=(512, 512))

After (Gradio 6.x):

editor = gr.ImageEditor(canvas_size=(512, 512))

Removed components

gr.LogoutButton - This component has been removed. Use gr.LoginButton instead, which handles both login and logout processes.

Before (Gradio 5.x):

logout_btn = gr.LogoutButton()

After (Gradio 6.x):

login_btn = gr.LoginButton()

Native plot components removed parameters

The following parameters have been removed from gr.LinePlot, gr.BarPlot, and gr.ScatterPlot:

  • overlay_point - This parameter has been removed.
  • width - This parameter has been removed. Use CSS styling or container width instead.
  • stroke_dash - This parameter has been removed.
  • interactive - This parameter has been removed.
  • show_actions_button - This parameter has been removed.
  • color_legend_title - This parameter has been removed. Use color_title instead.
  • show_fullscreen_button, show_export_button - These parameters have been removed. Use the buttons parameter instead.

Before (Gradio 5.x):

plot = gr.LinePlot(
    value=data,
    x="date",
    y="downloads",
    overlay_point=True,
    width=900,
    show_fullscreen_button=True,
    show_export_button=True
)

After (Gradio 6.x):

plot = gr.LinePlot(
    value=data,
    x="date",
    y="downloads",
    buttons=["fullscreen", "export"]
)

Note: For color_legend_title, use color_title instead:

Before (Gradio 5.x):

plot = gr.ScatterPlot(color_legend_title="Category")

After (Gradio 6.x):

plot = gr.ScatterPlot(color_title="Category")

gr.Textbox removed parameters

show_copy_button - This parameter has been removed. Use the buttons parameter instead.

Before (Gradio 5.x):

text = gr.Textbox(show_copy_button=True)

After (Gradio 6.x):

text = gr.Textbox(buttons=["copy"])

gr.Markdown removed parameters

show_copy_button - This parameter has been removed. Use the buttons parameter instead.

Before (Gradio 5.x):

markdown = gr.Markdown(show_copy_button=True)

After (Gradio 6.x):

markdown = gr.Markdown(buttons=["copy"])

gr.Dataframe removed parameters

show_copy_button, show_fullscreen_button - These parameters have been removed. Use the buttons parameter instead.

Before (Gradio 5.x):

df = gr.Dataframe(show_copy_button=True, show_fullscreen_button=True)

After (Gradio 6.x):

df = gr.Dataframe(buttons=["copy", "fullscreen"])

gr.Slider removed parameters

show_reset_button - This parameter has been removed. Use the buttons parameter instead.

Before (Gradio 5.x):

slider = gr.Slider(show_reset_button=True)

After (Gradio 6.x):

slider = gr.Slider(buttons=["reset"])

CLI Changes

gradio sketch command removed

The gradio sketch command-line tool has been deprecated and completely removed in Gradio 6. This tool was used to create Gradio apps through a visual interface.

In Gradio 5.x:

  • You could run gradio sketch to launch an interactive GUI for building Gradio apps
  • The tool would generate Python code visually

In Gradio 6.x:

  • The gradio sketch command has been removed
  • Running gradio sketch will raise a DeprecationWarning

Python Client Changes

hf_token parameter renamed to token in Client

The hf_token parameter in the Client class has been renamed to token for consistency and simplicity.

Before (Gradio 5.x):

from gradio_client import Client

client = Client("abidlabs/my-private-space", hf_token="hf_...")

After (Gradio 6.x):

from gradio_client import Client

client = Client("abidlabs/my-private-space", token="hf_...")

deploy_discord method deprecated

The deploy_discord method in the Client class has been deprecated and will be removed in Gradio 6.0. This method was used to deploy Gradio apps as Discord bots.

Before (Gradio 5.x):

from gradio_client import Client

client = Client("username/space-name")
client.deploy_discord(discord_bot_token="...")

After (Gradio 6.x):

The deploy_discord method is no longer available. Please see the documentation on creating a Discord bot with Gradio for alternative approaches.

AppError now subclasses Exception instead of ValueError

The AppError exception class in the Python client now subclasses Exception directly instead of ValueError. This is a breaking change if you have code that specifically catches ValueError to handle AppError instances.

Before (Gradio 5.x):

from gradio_client import Client
from gradio_client.exceptions import AppError

try:
    client = Client("username/space-name")
    result = client.predict("/predict", inputs)
except ValueError as e:
    # This would catch AppError in Gradio 5.x
    print(f"Error: {e}")

After (Gradio 6.x):

from gradio_client import Client
from gradio_client.exceptions import AppError

try:
    client = Client("username/space-name")
    result = client.predict("/predict", inputs)
except AppError as e:
    # Explicitly catch AppError
    print(f"App error: {e}")
except ValueError as e:
    # This will no longer catch AppError
    print(f"Value error: {e}")

Quickstart

Gradio is an open-source Python package that allows you to quickly build a demo or web application for your machine learning model, API, or any arbitrary Python function. You can then share a link to your demo or web application in just a few seconds using Gradio's built-in sharing features. No JavaScript, CSS, or web hosting experience needed!

It just takes a few lines of Python to create your own demo, so let's get started 💫

Installation

Prerequisite: Gradio requires Python 3.10 or higher.

We recommend installing Gradio using pip, which is included by default in Python. Run this in your terminal or command prompt:

pip install --upgrade gradio
        <div class='tip'>
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                <path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/>
                <path d="M9 18h6"/>
                <path d="M10 22h4"/>
            </svg>
            <div><p>It is best to install Gradio in a virtual environment. Detailed installation instructions for all common operating systems <a href="https://www.gradio.app/main/guides/installing-gradio-in-a-virtual-environment">are provided here</a>. </p></div>
        </div>
            

Building Your First Demo

You can run Gradio in your favorite code editor, Jupyter notebook, Google Colab, or anywhere else you write Python. Let's write your first Gradio app:

import gradio as gr

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

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

demo.launch()

        <div class='tip'>
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                <path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/>
                <path d="M9 18h6"/>
                <path d="M10 22h4"/>
            </svg>
            <div><p>We shorten the imported name from <code>gradio</code> to <code>gr</code>. This is a widely adopted convention for better readability of code. </p></div>
        </div>
            

Now, run your code. If you've written the Python code in a file named app.py, then you would run python app.py from the terminal.

The demo below will open in a browser on http://localhost:7860 if running from a file. If you are running within a notebook, the demo will appear embedded within the notebook.

Type your name in the textbox on the left, drag the slider, and then press the Submit button. You should see a friendly greeting on the right. When developing locally, you can run your Gradio app in hot reload mode, which automatically reloads the Gradio app whenever you make changes to the file. To do this, simply type in gradio before the name of the file instead of python. In the example above, you would type: gradio app.py in your terminal. You can also enable vibe mode by using the --vibe flag, e.g. gradio --vibe app.py, which provides an in-browser chat that can be used to write or edit your Gradio app using natural language. Learn more in the Hot Reloading Guide.

Understanding the Interface Class

You'll notice that in order to make your first demo, you created an instance of the gr.Interface class. The Interface class is designed to create demos for machine learning models which accept one or more inputs, and return one or more outputs.

The Interface class has three core arguments:

  • fn: the function to wrap a user interface (UI) around
  • inputs: the Gradio component(s) to use for the input. The number of components should match the number of arguments in your function.
  • outputs: the Gradio component(s) to use for the output. The number of components should match the number of return values from your function.

The fn argument is very flexible -- you can pass any Python function that you want to wrap with a UI. In the example above, we saw a relatively simple function, but the function could be anything from a music generator to a tax calculator to the prediction function of a pretrained machine learning model.

The inputs and outputs arguments take one or more Gradio components. As we'll see, Gradio includes more than 30 built-in components (such as the gr.Textbox(), gr.Image(), and gr.HTML() components) that are designed for machine learning applications. For the inputs and outputs arguments, you can pass in the name of these components as a string ("textbox") or an instance of the class (gr.Textbox()).

If your function accepts more than one argument, as is the case above, pass a list of input components to inputs, with each input component corresponding to one of the arguments of the function, in order. The same holds true if your function returns more than one value: simply pass in a list of components to outputs. This flexibility makes the Interface class a very powerful way to create demos.

We'll dive deeper into the gr.Interface on our series on building Interfaces.

Sharing Your Demo

What good is a beautiful demo if you can't share it? Gradio lets you easily share a machine learning demo without having to worry about the hassle of hosting on a web server. Simply set share=True in launch(), and a publicly accessible URL will be created for your demo. Let's revisit our example demo, but change the last line as follows:

import gradio as gr

def greet(name):
    return "Hello " + name + "!"

demo = gr.Interface(fn=greet, inputs="textbox", outputs="textbox")
    
demo.launch(share=True)  # Share your demo with just 1 extra parameter 🚀

When you run this code, a public URL will be generated for your demo in a matter of seconds, something like:

👉   https://a23dsf231adb.gradio.live

Now, anyone around the world can try your Gradio demo from their browser, while the machine learning model and all computation continues to run locally on your computer.

To learn more about sharing your demo, read our dedicated guide on sharing your Gradio application.

An Overview of Gradio

So far, we've been discussing the Interface class, which is a high-level class that lets you build demos quickly with Gradio. But what else does Gradio include?

Custom Demos with gr.Blocks

Gradio offers a low-level approach for designing web apps with more customizable layouts and data flows with the gr.Blocks class. Blocks supports things like controlling where components appear on the page, handling multiple data flows and more complex interactions (e.g. outputs can serve as inputs to other functions), and updating properties/visibility of components based on user interaction — still all in Python.

You can build very custom and complex applications using gr.Blocks(). For example, the popular image generation Automatic1111 Web UI is built using Gradio Blocks. We dive deeper into the gr.Blocks on our series on building with Blocks.

Chatbots with gr.ChatInterface

Gradio includes another high-level class, gr.ChatInterface, which is specifically designed to create Chatbot UIs. Similar to Interface, you supply a function and Gradio creates a fully working Chatbot UI. If you're interested in creating a chatbot, you can jump straight to our dedicated guide on gr.ChatInterface.

The Gradio Python & JavaScript Ecosystem

That's the gist of the core gradio Python library, but Gradio is actually so much more! It's an entire ecosystem of Python and JavaScript libraries that let you build machine learning applications, or query them programmatically, in Python or JavaScript. Here are other related parts of the Gradio ecosystem:

  • Gradio Python Client (gradio_client): query any Gradio app programmatically in Python.
  • Gradio JavaScript Client (@gradio/client): query any Gradio app programmatically in JavaScript.
  • Hugging Face Spaces: the most popular place to host Gradio applications — for free!
  • Server mode (gradio.Server): build a completely custom frontend using only Gradio's backend (queue, streaming, MCP, ZeroGPU, and Spaces hosting included).

What's Next?

Keep learning about Gradio sequentially using the Gradio Guides, which include explanations as well as example code and embedded interactive demos. Next up: let's dive deeper into the Interface class.

Or, if you already know the basics and are looking for something specific, you can search the more technical API documentation.

The Interface class

As mentioned in the Quickstart, the gr.Interface class is a high-level abstraction in Gradio that allows you to quickly create a demo for any Python function simply by specifying the input types and the output types. Revisiting our first demo:

import gradio as gr

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

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

demo.launch()

We see that the Interface class is initialized with three required parameters:

  • fn: the function to wrap a user interface (UI) around
  • inputs: which Gradio component(s) to use for the input. The number of components should match the number of arguments in your function.
  • outputs: which Gradio component(s) to use for the output. The number of components should match the number of return values from your function.

In this Guide, we'll dive into gr.Interface and the various ways it can be customized, but before we do that, let's get a better understanding of Gradio components.

Gradio Components

Gradio includes more than 30 pre-built components (as well as many community-built custom components) that can be used as inputs or outputs in your demo. These components correspond to common data types in machine learning and data science, e.g. the gr.Image component is designed to handle input or output images, the gr.Label component displays classification labels and probabilities, the gr.LinePlot component displays line plots, and so on.

Components Attributes

We used the default versions of the gr.Textbox and gr.Slider, but what if you want to change how the UI components look or behave?

Let's say you want to customize the slider to have values from 1 to 10, with a default of 2. And you wanted to customize the output text field — you want it to be larger and have a label.

If you use the actual classes for gr.Textbox and gr.Slider instead of the string shortcuts, you have access to much more customizability through component attributes.

import gradio as gr

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

demo = gr.Interface(
    fn=greet,
    inputs=["text", gr.Slider(value=2, minimum=1, maximum=10, step=1)],
    outputs=[gr.Textbox(label="greeting", lines=3)],
    api_name="predict"
)

demo.launch()

Multiple Input and Output Components

Suppose you had a more complex function, with multiple outputs as well. In the example below, we define a function that takes a string, boolean, and number, and returns a string and number.

import gradio as gr

def greet(name, is_morning, temperature):
    salutation = "Good morning" if is_morning else "Good evening"
    greeting = f"{salutation} {name}. It is {temperature} degrees today"
    celsius = (temperature - 32) * 5 / 9
    return greeting, round(celsius, 2)

demo = gr.Interface(
    fn=greet,
    inputs=["text", "checkbox", gr.Slider(0, 100)],
    outputs=["text", "number"],
    api_name="predict"
)
demo.launch()

Just as each component in the inputs list corresponds to one of the parameters of the function, in order, each component in the outputs list corresponds to one of the values returned by the function, in order.

An Image Example

Gradio supports many types of components, such as Image, DataFrame, Video, or Label. Let's try an image-to-image function to get a feel for these!

import numpy as np
import gradio as gr

def sepia(input_img):
    sepia_filter = np.array([
        [0.393, 0.769, 0.189],
        [0.349, 0.686, 0.168],
        [0.272, 0.534, 0.131]
    ])
    sepia_img = input_img.dot(sepia_filter.T)
    sepia_img /= sepia_img.max()
    return sepia_img

demo = gr.Interface(sepia, gr.Image(), "image", api_name="predict")
demo.launch()

When using the Image component as input, your function will receive a NumPy array with the shape (height, width, 3), where the last dimension represents the RGB values. We'll return an image as well in the form of a NumPy array.

Gradio handles the preprocessing and postprocessing to convert images to NumPy arrays and vice versa. You can also control the preprocessing performed with the type= keyword argument. For example, if you wanted your function to take a file path to an image instead of a NumPy array, the input Image component could be written as:

gr.Image(type="filepath")

You can read more about the built-in Gradio components and how to customize them in the Gradio docs.

Example Inputs

You can provide example data that a user can easily load into Interface. This can be helpful to demonstrate the types of inputs the model expects, as well as to provide a way to explore your dataset in conjunction with your model. To load example data, you can provide a nested list to the examples= keyword argument of the Interface constructor. Each sublist within the outer list represents a data sample, and each element within the sublist represents an input for each input component. The format of example data for each component is specified in the Docs.

import gradio as gr

def calculator(num1, operation, num2):
    if operation == "add":
        return num1 + num2
    elif operation == "subtract":
        return num1 - num2
    elif operation == "multiply":
        return num1 * num2
    elif operation == "divide":
        if num2 == 0:
            raise gr.Error("Cannot divide by zero!")
        return num1 / num2

demo = gr.Interface(
    calculator,
    [
        "number",
        gr.Radio(["add", "subtract", "multiply", "divide"]),
        "number"
    ],
    "number",
    examples=[
        [45, "add", 3],
        [3.14, "divide", 2],
        [144, "multiply", 2.5],
        [0, "subtract", 1.2],
    ],
    title="Toy Calculator",
    description="Here's a sample toy calculator.",
    api_name="predict"
)

demo.launch()

You can load a large dataset into the examples to browse and interact with the dataset through Gradio. The examples will be automatically paginated (you can configure this through the examples_per_page argument of Interface).

Continue learning about examples in the More On Examples guide.

Descriptive Content

In the previous example, you may have noticed the title= and description= keyword arguments in the Interface constructor that helps users understand your app.

There are three arguments in the Interface constructor to specify where this content should go:

  • title: which accepts text and can display it at the very top of interface, and also becomes the page title.
  • description: which accepts text, markdown or HTML and places it right under the title.
  • article: which also accepts text, markdown or HTML and places it below the interface.

annotated

Another useful keyword argument is label=, which is present in every Component. This modifies the label text at the top of each Component. You can also add the info= keyword argument to form elements like Textbox or Radio to provide further information on their usage.

gr.Number(label='Age', info='In years, must be greater than 0')

Additional Inputs within an Accordion

If your prediction function takes many inputs, you may want to hide some of them within a collapsed accordion to avoid cluttering the UI. The Interface class takes an additional_inputs argument which is similar to inputs but any input components included here are not visible by default. The user must click on the accordion to show these components. The additional inputs are passed into the prediction function, in order, after the standard inputs.

You can customize the appearance of the accordion by using the optional additional_inputs_accordion argument, which accepts a string (in which case, it becomes the label of the accordion), or an instance of the gr.Accordion() class (e.g. this lets you control whether the accordion is open or closed by default).

Here's an example:

import gradio as gr

def generate_fake_image(prompt, seed, initial_image=None):
    return f"Used seed: {seed}", "https://dummyimage.com/300/09f.png"

demo = gr.Interface(
    generate_fake_image,
    inputs=["textbox"],
    outputs=["textbox", "image"],
    additional_inputs=[
        gr.Slider(0, 1000),
        "image"
    ],
    api_name="predict",
)

demo.launch()


Blocks and Event Listeners

We briefly described the Blocks class in the Quickstart as a way to build custom demos. Let's dive deeper.

Blocks Structure

Take a look at the demo below.

import gradio as gr


def greet(name):
    return "Hello " + name + "!"


with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    output = gr.Textbox(label="Output Box")
    greet_btn = gr.Button("Greet")
    greet_btn.click(fn=greet, inputs=name, outputs=output, api_name="greet")

demo.launch()

  • First, note the with gr.Blocks() as demo: clause. The Blocks app code will be contained within this clause.
  • Next come the Components. These are the same Components used in Interface. However, instead of being passed to some constructor, Components are automatically added to the Blocks as they are created within the with clause.
  • Finally, the click() event listener. Event listeners define the data flow within the app. In the example above, the listener ties the two Textboxes together. The Textbox name acts as the input and Textbox output acts as the output to the greet method. This dataflow is triggered when the Button greet_btn is clicked. Like an Interface, an event listener can take multiple inputs or outputs.

You can also attach event listeners using decorators - skip the fn argument and assign inputs and outputs directly:

import gradio as gr

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    output = gr.Textbox(label="Output Box")
    greet_btn = gr.Button("Greet")

    @greet_btn.click(inputs=name, outputs=output)
    def greet(name):
        return "Hello " + name + "!"

demo.launch()

Event Listeners and Interactivity

In the example above, you'll notice that you are able to edit Textbox name, but not Textbox output. This is because any Component that acts as an input to an event listener is made interactive. However, since Textbox output acts only as an output, Gradio determines that it should not be made interactive. You can override the default behavior and directly configure the interactivity of a Component with the boolean interactive keyword argument, e.g. gr.Textbox(interactive=True).

output = gr.Textbox(label="Output", interactive=True)

Note: What happens if a Gradio component is neither an input nor an output? If a component is constructed with a default value, then it is presumed to be displaying content and is rendered non-interactive. Otherwise, it is rendered interactive. Again, this behavior can be overridden by specifying a value for the interactive argument.

Types of Event Listeners

Take a look at the demo below:

import gradio as gr

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

with gr.Blocks() as demo:
    gr.Markdown(
    """
    # Hello World!
    Start typing below to see the output.
    """)
    inp = gr.Textbox(placeholder="What is your name?")
    out = gr.Textbox()
    inp.change(welcome, inp, out)

demo.launch()

Instead of being triggered by a click, the welcome function is triggered by typing in the Textbox inp. This is due to the change() event listener. Different Components support different event listeners. For example, the Video Component supports a play() event listener, triggered when a user presses play. See the Docs for the event listeners for each Component.

Multiple Data Flows

A Blocks app is not limited to a single data flow the way Interfaces are. Take a look at the demo below:

import gradio as gr

def increase(num):
    return num + 1

with gr.Blocks() as demo:
    a = gr.Number(label="a")
    b = gr.Number(label="b")
    atob = gr.Button("a > b")
    btoa = gr.Button("b > a")
    atob.click(increase, a, b)
    btoa.click(increase, b, a)

demo.launch()

Note that num1 can act as input to num2, and also vice-versa! As your apps get more complex, you will have many data flows connecting various Components.

Here's an example of a "multi-step" demo, where the output of one model (a speech-to-text model) gets fed into the next model (a sentiment classifier).

from transformers import pipeline

import gradio as gr

asr = pipeline("automatic-speech-recognition", "facebook/wav2vec2-base-960h")
classifier = pipeline("text-classification")

def speech_to_text(speech):
    text = asr(speech)["text"]  
    return text

def text_to_sentiment(text):
    return classifier(text)[0]["label"]  

demo = gr.Blocks()

with demo:
    audio_file = gr.Audio(type="filepath")
    text = gr.Textbox()
    label = gr.Label()

    b1 = gr.Button("Recognize Speech")
    b2 = gr.Button("Classify Sentiment")

    b1.click(speech_to_text, inputs=audio_file, outputs=text)
    b2.click(text_to_sentiment, inputs=text, outputs=label)

demo.launch()

Function Input List vs Set

The event listeners you've seen so far have a single input component. If you'd like to have multiple input components pass data to the function, you have two options on how the function can accept input component values:

  1. as a list of arguments, or
  2. as a single dictionary of values, keyed by the component

Let's see an example of each:

import gradio as gr

with gr.Blocks() as demo:
    a = gr.Number(label="a")
    b = gr.Number(label="b")
    with gr.Row():
        add_btn = gr.Button("Add")
        sub_btn = gr.Button("Subtract")
    c = gr.Number(label="sum")

    def add(num1, num2):
        return num1 + num2
    add_btn.click(add, inputs=[a, b], outputs=c)

    def sub(data):
        return data[a] - data[b]
    sub_btn.click(sub, inputs={a, b}, outputs=c)

demo.launch()

Both add() and sub() take a and b as inputs. However, the syntax is different between these listeners.

  1. To the add_btn listener, we pass the inputs as a list. The function add() takes each of these inputs as arguments. The value of a maps to the argument num1, and the value of b maps to the argument num2.
  2. To the sub_btn listener, we pass the inputs as a set (note the curly brackets!). When you pass a set, the function sub() receives a single dictionary argument data, where the keys are the input components and the values are the values of those components.

It is a matter of preference which syntax you prefer! For functions with many input components, option 2 may be easier to manage.

Function Return List vs Dict

Similarly, you may return values for multiple output components either as:

  1. a list of values, or
  2. a dictionary keyed by the component

Let's first see an example of (1), where we set the values of two output components by returning two values:

with gr.Blocks() as demo:
    food_box = gr.Number(value=10, label="Food Count")
    status_box = gr.Textbox()

    def eat(food):
        if food > 0:
            return food - 1, "full"
        else:
            return 0, "hungry"

    gr.Button("Eat").click(
        fn=eat,
        inputs=food_box,
        outputs=[food_box, status_box]
    )

Above, each return statement returns two values corresponding to food_box and status_box, respectively.

Note: if your event listener has a single output component, you should not return it as a single-item list. This will not work, since Gradio does not know whether to interpret that outer list as part of your return value. You should instead just return that value directly.

Now, let's see option (2). Instead of returning a list of values corresponding to each output component in order, you can also return a dictionary, with the key corresponding to the output component and the value as the new value. This also allows you to skip updating some output components.

with gr.Blocks() as demo:
    food_box = gr.Number(value=10, label="Food Count")
    status_box = gr.Textbox()

    def eat(food):
        if food > 0:
            return {food_box: food - 1, status_box: "full"}
        else:
            return {status_box: "hungry"}

    gr.Button("Eat").click(
        fn=eat,
        inputs=food_box,
        outputs=[food_box, status_box]
    )

Notice how when there is no food, we only update the status_box element. We skipped updating the food_box component.

Dictionary returns are helpful when an event listener affects many components on return, or conditionally affects outputs and not others.

Keep in mind that with dictionary returns, we still need to specify the possible outputs in the event listener.

Updating Component Configurations

The return value of an event listener function is usually the updated value of the corresponding output Component. Sometimes we want to update the configuration of the Component as well, such as the visibility. In this case, we return a new Component, setting the properties we want to change.

import gradio as gr

def change_textbox(choice):
    if choice == "short":
        return gr.Textbox(lines=2, visible=True)
    elif choice == "long":
        return gr.Textbox(lines=8, visible=True, value="Lorem ipsum dolor sit amet")
    else:
        return gr.Textbox(visible=False)

with gr.Blocks() as demo:
    radio = gr.Radio(
        ["short", "long", "none"], label="What kind of essay would you like to write?"
    )
    text = gr.Textbox(lines=2, interactive=True, buttons=["copy"])
    radio.change(fn=change_textbox, inputs=radio, outputs=text)

demo.launch()

See how we can configure the Textbox itself through a new gr.Textbox() method. The value= argument can still be used to update the value along with Component configuration. Any arguments we do not set will preserve their previous values.

Not Changing a Component's Value

In some cases, you may want to leave a component's value unchanged. Gradio includes a special function, gr.skip(), which can be returned from your function. Returning this function will keep the output component (or components') values as is. Let us illustrate with an example:

import random
import gradio as gr

with gr.Blocks() as demo:
    with gr.Row():
        clear_button = gr.Button("Clear")
        skip_button = gr.Button("Skip")
        random_button = gr.Button("Random")
    numbers = [gr.Number(), gr.Number()]

    clear_button.click(lambda : (None, None), outputs=numbers)
    skip_button.click(lambda : [gr.skip(), gr.skip()], outputs=numbers)
    random_button.click(lambda : (random.randint(0, 100), random.randint(0, 100)), outputs=numbers)

demo.launch()

Note the difference between returning None (which generally resets a component's value to an empty state) versus returning gr.skip(), which leaves the component value unchanged. if you have multiple output components, and you want to leave all of their values unchanged, you can just return a single gr.skip() instead of returning a tuple of skips, one for each element.

Running Events Consecutively

You can also run events consecutively by using the then method of an event listener. This will run an event after the previous event has finished running. This is useful for running events that update components in multiple steps.

For example, in the chatbot example below, we first update the chatbot with the user message immediately, and then update the chatbot with the computer response after a simulated delay.

import gradio as gr
import random
import time

with gr.Blocks() as demo:
    chatbot = gr.Chatbot()
    msg = gr.Textbox()
    clear = gr.Button("Clear")

    def user(user_message, history):
        return "", history + [{"role": "user", "content": user_message}]

    def bot(history):
        bot_message = random.choice(["How are you?", "I love you", "I'm very hungry"])
        time.sleep(2)
        history.append({"role": "assistant", "content": bot_message})
        return history

    msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
        bot, chatbot, chatbot
    )
    clear.click(lambda: None, None, chatbot, queue=False)

demo.launch()

The .then() method of an event listener executes the subsequent event regardless of whether the previous event raised any errors. If you'd like to only run subsequent events if the previous event executed successfully, use the .success() method, which takes the same arguments as .then(). Conversely, if you'd like to only run subsequent events if the previous event failed (i.e., raised an error), use the .failure() method. This is particularly useful for error handling workflows, such as displaying error messages or restoring previous states when an operation fails.

Binding Multiple Triggers to a Function

Often times, you may want to bind multiple triggers to the same function. For example, you may want to allow a user to click a submit button, or press enter to submit a form. You can do this using the gr.on method and passing a list of triggers to the trigger.

import gradio as gr

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    output = gr.Textbox(label="Output Box")
    greet_btn = gr.Button("Greet")
    trigger = gr.Textbox(label="Trigger Box")

    def greet(name, evt_data: gr.EventData):
        return "Hello " + name + "!", evt_data.target.__class__.__name__

    def clear_name(evt_data: gr.EventData):
        return ""

    gr.on(
        triggers=[name.submit, greet_btn.click],
        fn=greet,
        inputs=name,
        outputs=[output, trigger],
    ).then(clear_name, outputs=[name])

demo.launch()

You can use decorator syntax as well:

import gradio as gr

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    output = gr.Textbox(label="Output Box")
    greet_btn = gr.Button("Greet")

    @gr.on(triggers=[name.submit, greet_btn.click], inputs=name, outputs=output)
    def greet(name):
        return "Hello " + name + "!"

demo.launch()

You can use gr.on to create "live" events by binding to the change event of components that implement it. If you do not specify any triggers, the function will automatically bind to all change event of all input components that include a change event (for example gr.Textbox has a change event whereas gr.Button does not).

import gradio as gr

with gr.Blocks() as demo:
    with gr.Row():
        num1 = gr.Slider(1, 10)
        num2 = gr.Slider(1, 10)
        num3 = gr.Slider(1, 10)
    output = gr.Number(label="Sum")

    @gr.on(inputs=[num1, num2, num3], outputs=output)
    def sum(a, b, c):
        return a + b + c

demo.launch()

You can follow gr.on with .then, just like any regular event listener. This handy method should save you from having to write a lot of repetitive code!

Binding a Component Value Directly to a Function of Other Components

If you want to set a Component's value to always be a function of the value of other Components, you can use the following shorthand:

with gr.Blocks() as demo:
  num1 = gr.Number()
  num2 = gr.Number()
  product = gr.Number(lambda a, b: a * b, inputs=[num1, num2])

This functionally the same as:

with gr.Blocks() as demo:
  num1 = gr.Number()
  num2 = gr.Number()
  product = gr.Number()

  gr.on(
    [num1.change, num2.change, demo.load], 
    lambda a, b: a * b, 
    inputs=[num1, num2], 
    outputs=product
  )

Controlling Layout

By default, Components in Blocks are arranged vertically. Let's take a look at how we can rearrange Components. Under the hood, this layout structure uses the flexbox model of web development.

Rows

Elements within a with gr.Row clause will all be displayed horizontally. For example, to display two Buttons side by side:

with gr.Blocks() as demo:
    with gr.Row():
        btn1 = gr.Button("Button 1")
        btn2 = gr.Button("Button 2")

You can set every element in a Row to have the same height. Configure this with the equal_height argument.

with gr.Blocks() as demo:
    with gr.Row(equal_height=True):
        textbox = gr.Textbox()
        btn2 = gr.Button("Button 2")

The widths of elements in a Row can be controlled via a combination of scale and min_width arguments that are present in every Component.

  • scale is an integer that defines how an element will take up space in a Row. If scale is set to 0, the element will not expand to take up space. If scale is set to 1 or greater, the element will expand. Multiple elements in a row will expand proportional to their scale. Below, btn2 will expand twice as much as btn1, while btn0 will not expand at all:
with gr.Blocks() as demo:
    with gr.Row():
        btn0 = gr.Button("Button 0", scale=0)
        btn1 = gr.Button("Button 1", scale=1)
        btn2 = gr.Button("Button 2", scale=2)
  • min_width will set the minimum width the element will take. The Row will wrap if there isn't sufficient space to satisfy all min_width values.

Learn more about Rows in the docs.

Columns and Nesting

Components within a Column will be placed vertically atop each other. Since the vertical layout is the default layout for Blocks apps anyway, to be useful, Columns are usually nested within Rows. For example:

import gradio as gr

with gr.Blocks() as demo:
    with gr.Row():
        text1 = gr.Textbox(label="t1")
        slider2 = gr.Textbox(label="s2")
        drop3 = gr.Dropdown(["a", "b", "c"], label="d3")
    with gr.Row():
        with gr.Column(scale=1, min_width=300):
            text1 = gr.Textbox(label="prompt 1")
            text2 = gr.Textbox(label="prompt 2")
            inbtw = gr.Button("Between")
            text4 = gr.Textbox(label="prompt 1")
            text5 = gr.Textbox(label="prompt 2")
        with gr.Column(scale=2, min_width=300):
            img1 = gr.Image("images/cheetah.jpg")
            btn = gr.Button("Go")

demo.launch()

See how the first column has two Textboxes arranged vertically. The second column has an Image and Button arranged vertically. Notice how the relative widths of the two columns is set by the scale parameter. The column with twice the scale value takes up twice the width.

Learn more about Columns in the docs.

Fill Browser Height / Width

To make an app take the full width of the browser by removing the side padding, use gr.Blocks(fill_width=True).

To make top level Components expand to take the full height of the browser, use fill_height and apply scale to the expanding Components.

import gradio as gr

with gr.Blocks(fill_height=True) as demo:
    gr.Chatbot(scale=1)
    gr.Textbox(scale=0)

Dimensions

Some components support setting height and width. These parameters accept either a number (interpreted as pixels) or a string. Using a string allows the direct application of any CSS unit to the encapsulating Block element.

Below is an example illustrating the use of viewport width (vw):

import gradio as gr

with gr.Blocks() as demo:
    im = gr.ImageEditor(width="50vw")

demo.launch()

Tabs and Accordions

You can also create Tabs using the with gr.Tab('tab_name'): clause. Any component created inside of a with gr.Tab('tab_name'): context appears in that tab. Consecutive Tab clauses are grouped together so that a single tab can be selected at one time, and only the components within that Tab's context are shown.

For example:

import numpy as np
import gradio as gr

def flip_text(x):
    return x[::-1]

def flip_image(x):
    return np.fliplr(x)

with gr.Blocks() as demo:
    gr.Markdown("Flip text or image files using this demo.")
    with gr.Tab("Flip Text"):
        text_input = gr.Textbox()
        text_output = gr.Textbox()
        text_button = gr.Button("Flip")
    with gr.Tab("Flip Image"):
        with gr.Row():
            image_input = gr.Image()
            image_output = gr.Image()
        image_button = gr.Button("Flip")

    with gr.Accordion("Open for More!", open=False):
        gr.Markdown("Look at me...")
        temp_slider = gr.Slider(
            0, 1,
            value=0.1,
            step=0.1,
            interactive=True,
            label="Slide me",
        )

    text_button.click(flip_text, inputs=text_input, outputs=text_output)
    image_button.click(flip_image, inputs=image_input, outputs=image_output)

demo.launch()

Also note the gr.Accordion('label') in this example. The Accordion is a layout that can be toggled open or closed. Like Tabs, it is a layout element that can selectively hide or show content. Any components that are defined inside of a with gr.Accordion('label'): will be hidden or shown when the accordion's toggle icon is clicked.

Learn more about Tabs and Accordions in the docs.

Sidebar

The sidebar is a collapsible panel that renders child components on the left side of the screen and can be expanded or collapsed.

For example:

import gradio as gr
import random

def generate_pet_name(animal_type, personality):
    cute_prefixes = ["Fluffy", "Ziggy", "Bubbles", "Pickle", "Waffle", "Mochi", "Cookie", "Pepper"]
    animal_suffixes = {
        "Cat": ["Whiskers", "Paws", "Mittens", "Purrington"],
        "Dog": ["Woofles", "Barkington", "Waggins", "Pawsome"],
        "Bird": ["Feathers", "Wings", "Chirpy", "Tweets"],
        "Rabbit": ["Hops", "Cottontail", "Bouncy", "Fluff"]
    }

    prefix = random.choice(cute_prefixes)
    suffix = random.choice(animal_suffixes[animal_type])

    if personality == "Silly":
        prefix = random.choice(["Sir", "Lady", "Captain", "Professor"]) + " " + prefix
    elif personality == "Royal":
        suffix += " the " + random.choice(["Great", "Magnificent", "Wise", "Brave"])

    return f"{prefix} {suffix}"

with gr.Blocks() as demo:
    with gr.Sidebar(position="left"):
        gr.Markdown("# 🐾 Pet Name Generator")
        gr.Markdown("Use the options below to generate a unique pet name!")

        animal_type = gr.Dropdown(
            choices=["Cat", "Dog", "Bird", "Rabbit"],
            label="Choose your pet type",
            value="Cat"
        )
        personality = gr.Radio(
            choices=["Normal", "Silly", "Royal"],
            label="Personality type",
            value="Normal"
        )

    name_output = gr.Textbox(label="Your pet's fancy name:", lines=2)
    generate_btn = gr.Button("Generate Name! 🎲", variant="primary")
    generate_btn.click(
        fn=generate_pet_name,
        inputs=[animal_type, personality],
        outputs=name_output
    )

if __name__ == "__main__":
    demo.launch(theme=gr.themes.Soft())

Learn more about Sidebar in the docs.

Multi-step walkthroughs

In order to provide a guided set of ordered steps, a controlled workflow, you can use the Walkthrough component with accompanying Step components.

The Walkthrough component has a visual style and user experience tailored for this usecase.

Authoring this component is very similar to Tab, except it is the app developers responsibility to progress through each step, by setting the appropriate ID for the parent Walkthrough which should correspond to an ID provided to an indvidual Step.

Learn more about Walkthrough in the docs.

Visibility

Both Components and Layout elements have a visible argument that can set initially and also updated. Setting gr.Column(visible=...) on a Column can be used to show or hide a set of Components.

import gradio as gr

with gr.Blocks() as demo:
    name_box = gr.Textbox(label="Name")
    age_box = gr.Number(label="Age", minimum=0, maximum=100)
    symptoms_box = gr.CheckboxGroup(["Cough", "Fever", "Runny Nose"])
    submit_btn = gr.Button("Submit")

    with gr.Column(visible=False) as output_col:
        diagnosis_box = gr.Textbox(label="Diagnosis")
        patient_summary_box = gr.Textbox(label="Patient Summary")

    def submit(name, age, symptoms):
        return {
            submit_btn: gr.Button(visible=False),
            output_col: gr.Column(visible=True),
            diagnosis_box: "covid" if "Cough" in symptoms else "flu",
            patient_summary_box: f"{name}, {age} y/o",
        }

    submit_btn.click(
        submit,
        [name_box, age_box, symptoms_box],
        [submit_btn, diagnosis_box, patient_summary_box, output_col],
    )

demo.launch()

Defining and Rendering Components Separately

In some cases, you might want to define components before you actually render them in your UI. For instance, you might want to show an examples section using gr.Examples above the corresponding gr.Textbox input. Since gr.Examples requires as a parameter the input component object, you will need to first define the input component, but then render it later, after you have defined the gr.Examples object.

The solution to this is to define the gr.Textbox outside of the gr.Blocks() scope and use the component's .render() method wherever you'd like it placed in the UI.

Here's a full code example:

input_textbox = gr.Textbox()

with gr.Blocks() as demo:
    gr.Examples(["hello", "bonjour", "merhaba"], input_textbox)
    input_textbox.render()

Similarly, if you have already defined a component in a Gradio app, but wish to unrender it so that you can define in a different part of your application, then you can call the .unrender() method. In the following example, the Textbox will appear in the third column:

import gradio as gr

with gr.Blocks() as demo:
    with gr.Row():
        with gr.Column():
            gr.Markdown("Row 1")
            textbox = gr.Textbox()
        with gr.Column():
            gr.Markdown("Row 2")
            textbox.unrender()
        with gr.Column():
            gr.Markdown("Row 3")
            textbox.render()

demo.launch()

More Blocks Features

Examples

Just like with gr.Interface, you can also add examples for your functions when you are working with gr.Blocks. In this case, instantiate a gr.Examples similar to how you would instantiate any other component. The constructor of gr.Examples takes two required arguments:

  • examples: a nested list of examples, in which the outer list consists of examples and each inner list consists of an input corresponding to each input component
  • inputs: the component or list of components that should be populated when the examples are clicked

You can also set cache_examples=True or cache_examples='lazy', similar to the caching API in gr.Interface, in which case two additional arguments must be provided:

  • outputs: the component or list of components corresponding to the output of the examples
  • fn: the function to run to generate the outputs corresponding to the examples

Here's an example showing how to use gr.Examples in a gr.Blocks app:

import gradio as gr

def calculator(num1, operation, num2):
    if operation == "add":
        return num1 + num2
    elif operation == "subtract":
        return num1 - num2
    elif operation == "multiply":
        return num1 * num2
    elif operation == "divide":
        return num1 / num2

with gr.Blocks() as demo:
    with gr.Row():
        with gr.Column():
            num_1 = gr.Number(value=4)
            operation = gr.Radio(["add", "subtract", "multiply", "divide"])
            num_2 = gr.Number(value=0)
            submit_btn = gr.Button(value="Calculate")
        with gr.Column():
            result = gr.Number()

    submit_btn.click(
        calculator, inputs=[num_1, operation, num_2], outputs=[result], api_visibility="private"
    )
    examples = gr.Examples(
        examples=[
            [5, "add", 3],
            [4, "divide", 2],
            [-4, "multiply", 2.5],
            [0, "subtract", 1.2],
        ],
        inputs=[num_1, operation, num_2],
    )

if __name__ == "__main__":
    demo.launch(footer_links=["gradio"])

Note: When you click on examples, not only does the value of the input component update to the example value, but the component's configuration also reverts to the properties with which you constructed the component. This ensures that the examples are compatible with the component even if its configuration has been changed.

Running Events Continuously

You can run events on a fixed schedule using gr.Timer() object. This will run the event when the timer's tick event fires. See the code below:

with gr.Blocks as demo:
    timer = gr.Timer(5)
    textbox = gr.Textbox()
    textbox2 = gr.Textbox()
    timer.tick(set_textbox_fn, textbox, textbox2)

This can also be used directly with a Component's every= parameter, if the value of the Component is a function:

with gr.Blocks as demo:
    timer = gr.Timer(5)
    textbox = gr.Textbox()
    textbox2 = gr.Textbox(set_textbox_fn, inputs=[textbox], every=timer)

Here is an example of a demo that print the current timestamp, and also prints random numbers regularly!

import gradio as gr
import random
import time

with gr.Blocks() as demo:
  timer = gr.Timer(1)
  timestamp = gr.Number(label="Time")
  timer.tick(lambda: round(time.time()), outputs=timestamp, api_name="timestamp")

  number = gr.Number(lambda: random.randint(1, 10), every=timer, label="Random Number")
  with gr.Row():
    gr.Button("Start").click(lambda: gr.Timer(active=True), None, timer)
    gr.Button("Stop").click(lambda: gr.Timer(active=False), None, timer)
    gr.Button("Go Fast").click(lambda: 0.2, None, timer)

if __name__ == "__main__":
  demo.launch()

Gathering Event Data

You can gather specific data about an event by adding the associated event data class as a type hint to an argument in the event listener function.

For example, event data for .select() can be type hinted by a gradio.SelectData argument. This event is triggered when a user selects some part of the triggering component, and the event data includes information about what the user specifically selected. For example, if a user selected a specific word in a Textbox, a specific pixel in an Image, a specific image in a Gallery, or a specific cell in a DataFrame, the event data argument would contain information about the specific selection.

The SelectData includes the value that was selected, and the index where the selection occurred. A simple example that shows what text was selected in a Textbox.

import gradio as gr

with gr.Blocks() as demo:
    textbox = gr.Textbox("The quick brown fox jumped.")
    selection = gr.Textbox()

    def get_selection(select_evt: gr.SelectData):
        return select_evt.value

    textbox.select(get_selection, None, selection)

In the 2 player tic-tac-toe demo below, a user can select a cell in the DataFrame to make a move. The event data argument contains information about the specific cell that was selected. We can first check to see if the cell is empty, and then update the cell with the user's move.

import gradio as gr

with gr.Blocks() as demo:
    turn = gr.Textbox("X", interactive=False, label="Turn")
    board = gr.Dataframe(value=[["", "", ""]] * 3, interactive=False, type="array")

    def place(board: list[list[int]], turn, evt: gr.SelectData):  
        if evt.value:
            return board, turn
        board[evt.index[0]][evt.index[1]] = turn
        turn = "O" if turn == "X" else "X"
        return board, turn

    board.select(place, [board, turn], [board, turn], show_progress="hidden")

demo.launch()

Validation

For certain apps, it is important to validate inputs prior to using them. While this can be done in the main event function, events also support a validator function dedicated to this task.

This feature allows for a far better user experience than placing this logic in your main function for the following reasons:

  • Input validation is performed immediately, bypassing the queue, giving the end user almost instant feedback.
  • Validation errors returned from the validator function are displayed differently in the UI.
  • The validator function allows for greater granularity. Rather than raising a generic exception, you can return a validation message and status for each input individually.

The validator kwarg should be a function that returns a gr.validate object for each input. gr.validate takes two arguments:

  • is_valid - whether or not the input is valid
  • message - the message to display if validation fails.

In the demo below you can see that by returning a validation status for each input, we have more granular information that we can display to the user.

import gradio as gr


def validate_input(age, location):
    return [
        gr.validate(not age or age > 3, "Age must be at least 3"),
        gr.validate("london" not in location.lower(), "Location must not be in London"),
    ]


def process_text(age, location):
    return f"Processed: {age} -- {location.upper()}"


with gr.Blocks() as demo:
    gr.Markdown("# Validator Parameter Test Demo")

    with gr.Row():
        with gr.Column():
            age = gr.Number(
                label="Enter age",
                placeholder="Enter age",
            )
            location = gr.Textbox(
                max_lines=3,
                label="Enter location",
                placeholder="Enter location",
            )

    validate_btn = gr.Button("Process with Validation", variant="primary")

    output_with_validation = gr.Textbox(
        label="Output (with validation)", interactive=False
    )

    validate_btn.click(
        fn=process_text,
        validator=validate_input,
        inputs=[age, location],
        outputs=output_with_validation,
    )


demo.launch()

Customizing your demo with CSS and Javascript

Gradio allows you to customize your demo in several ways. You can customize the layout of your demo, add custom HTML, and add custom theming as well. This tutorial will go beyond that and walk you through how to add custom CSS and JavaScript code to your demo in order to add custom styling, animations, custom UI functionality, analytics, and more.

Adding custom CSS to your demo

Gradio themes are the easiest way to customize the look and feel of your app. You can choose from a variety of themes, or create your own. To do so, pass the theme= kwarg to the launch() method of the Blocks constructor. For example:

with gr.Blocks() as demo:
    ... # your code here
demo.launch(theme=gr.themes.Glass())
    ...

Gradio comes with a set of prebuilt themes which you can load from gr.themes.*. You can extend these themes or create your own themes from scratch - see the Theming guide for more details.

For additional styling ability, you can pass any CSS to your app as a string using the css= kwarg in the launch() method. You can also pass a pathlib.Path to a css file or a list of such paths to the css_paths= kwarg in the launch() method.

Warning: The use of query selectors in custom JS and CSS is not guaranteed to work across Gradio versions that bind to Gradio's own HTML elements as the Gradio HTML DOM may change. We recommend using query selectors sparingly.

The base class for the Gradio app is gradio-container, so here's an example that changes the background color of the Gradio app:

with gr.Blocks() as demo:
    ... # your code here
demo.launch(css=".gradio-container {background-color: red}")
    ...

If you'd like to reference external files in your css, preface the file path (which can be a relative or absolute path) with "/gradio_api/file=", for example:

with gr.Blocks() as demo:
    ... # your code here
demo.launch(css=".gradio-container {background: url('/gradio_api/file=clouds.jpg')}")
    ...

Note: By default, most files in the host machine are not accessible to users running the Gradio app. As a result, you should make sure that any referenced files (such as clouds.jpg here) are either URLs or allowed paths, as described here.

The elem_id and elem_classes Arguments

You can elem_id to add an HTML element id to any component, and elem_classes to add a class or list of classes. This will allow you to select elements more easily with CSS. This approach is also more likely to be stable across Gradio versions as built-in class names or ids may change (however, as mentioned in the warning above, we cannot guarantee complete compatibility between Gradio versions if you use custom CSS as the DOM elements may themselves change).

css = """
#warning {background-color: #FFCCCB}
.feedback textarea {font-size: 24px !important}
"""

with gr.Blocks() as demo:
    box1 = gr.Textbox(value="Good Job", elem_classes="feedback")
    box2 = gr.Textbox(value="Failure", elem_id="warning", elem_classes="feedback")
demo.launch(css=css)

The CSS #warning ruleset will only target the second Textbox, while the .feedback ruleset will target both. Note that when targeting classes, you might need to put the !important selector to override the default Gradio styles.

Adding custom JavaScript to your demo

There are 3 ways to add javascript code to your Gradio demo:

  1. You can add JavaScript code as a string to the js parameter of the Blocks or Interface initializer. This will run the JavaScript code when the demo is first loaded.

Below is an example of adding custom js to show an animated welcome message when the demo first loads.

import gradio as gr

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

js = """
function createGradioAnimation() {
    var container = document.createElement('div');
    container.id = 'gradio-animation';
    container.style.fontSize = '2em';
    container.style.fontWeight = 'bold';
    container.style.textAlign = 'center';
    container.style.marginBottom = '20px';

    var text = 'Welcome to Gradio!';
    for (var i = 0; i < text.length; i++) {
        (function(i){
            setTimeout(function(){
                var letter = document.createElement('span');
                letter.style.opacity = '0';
                letter.style.transition = 'opacity 0.5s';
                letter.innerText = text[i];

                container.appendChild(letter);

                setTimeout(function() {
                    letter.style.opacity = '1';
                }, 50);
            }, i * 250);
        })(i);
    }

    var gradioContainer = document.querySelector('.gradio-container');
    gradioContainer.insertBefore(container, gradioContainer.firstChild);

    return 'Animation created';
}

createGradioAnimation();
"""

with gr.Blocks() as demo:
    inp = gr.Textbox(placeholder="What is your name?")
    out = gr.Textbox()
    inp.change(welcome, inp, out)

if __name__ == "__main__":
    demo.launch(js=js)

  1. When using Blocks and event listeners, events have a js argument that can take a JavaScript function as a string and treat it just like a Python event listener function. You can pass both a JavaScript function and a Python function (in which case the JavaScript function is run first) or only Javascript (and set the Python fn to None). Take a look at the code below:
import gradio as gr

blocks = gr.Blocks()

with blocks as demo:
    subject = gr.Textbox(placeholder="subject")
    verb = gr.Radio(["ate", "loved", "hated"])
    object = gr.Textbox(placeholder="object")

    with gr.Row():
        btn = gr.Button("Create sentence.")
        reverse_btn = gr.Button("Reverse sentence.")
        foo_bar_btn = gr.Button("Append foo")
        reverse_then_to_the_server_btn = gr.Button(
            "Reverse sentence and send to server."
        )

    def sentence_maker(w1, w2, w3):
        return f"{w1} {w2} {w3}"

    output1 = gr.Textbox(label="output 1")
    output2 = gr.Textbox(label="verb")
    output3 = gr.Textbox(label="verb reversed")
    output4 = gr.Textbox(label="front end process and then send to backend")

    btn.click(sentence_maker, [subject, verb, object], output1)
    reverse_btn.click(
        None, [subject, verb, object], output2, js="(s, v, o) => o + ' ' + v + ' ' + s"
    )
    verb.change(None, verb, output3, js="(x) => [...x].reverse().join('')")
    foo_bar_btn.click(None, [], subject, js="(x) => x + ' foo'")

    reverse_then_to_the_server_btn.click(
        None,
        [subject, verb, object],
        output4,
        js="(s, v, o) => [s, v, o].map(x => [...x].reverse().join('')).join(' ')",
    )

demo.launch()

  1. Lastly, you can add JavaScript code to the head param of the Blocks initializer. This will add the code to the head of the HTML document. For example, you can add Google Analytics to your demo like so:
head = f"""
<script async src="https://www.googletagmanager.com/gtag/js?id={google_analytics_tracking_id}"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){{dataLayer.push(arguments);}}
  gtag('js', new Date());
  gtag('config', '{google_analytics_tracking_id}');
</script>
"""

with gr.Blocks() as demo:
    gr.HTML("<h1>My App</h1>")

demo.launch(head=head)

The head parameter accepts any HTML tags you would normally insert into the <head> of a page. For example, you can also include <meta> tags to head in order to update the social sharing preview for your Gradio app like this:

import gradio as gr

custom_head = """
<!-- HTML Meta Tags -->
<title>Sample App</title>
<meta name="description" content="An open-source web application showcasing various features and capabilities.">

<!-- Facebook Meta Tags -->
<meta property="og:url" content="https://example.com">
<meta property="og:type" content="website">
<meta property="og:title" content="Sample App">
<meta property="og:description" content="An open-source web application showcasing various features and capabilities.">
<meta property="og:image" content="https://cdn.britannica.com/98/152298-050-8E45510A/Cheetah.jpg">

<!-- Twitter Meta Tags -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:creator" content="@example_user">
<meta name="twitter:title" content="Sample App">
<meta name="twitter:description" content="An open-source web application showcasing various features and capabilities.">
<meta name="twitter:image" content="https://cdn.britannica.com/98/152298-050-8E45510A/Cheetah.jpg">
<meta property="twitter:domain" content="example.com">
<meta property="twitter:url" content="https://example.com">  
"""

with gr.Blocks(title="My App") as demo:
    gr.HTML("<h1>My App</h1>")

demo.launch(head=custom_head)

Note that injecting custom JS can affect browser behavior and accessibility (e.g. keyboard shortcuts may be lead to unexpected behavior if your Gradio app is embedded in another webpage). You should test your interface across different browsers and be mindful of how scripts may interact with browser defaults. Here's an example where pressing Shift + s triggers the click event of a specific Button component if the browser focus is not on an input component (e.g. Textbox component):

import gradio as gr

shortcut_js = """
<script>
function shortcuts(e) {
    var event = document.all ? window.event : e;
    switch (e.target.tagName.toLowerCase()) {
        case "input":
        case "textarea":
        break;
        default:
        if (e.key.toLowerCase() == "s" && e.shiftKey) {
            document.getElementById("my_btn").click();
        }
    }
}
document.addEventListener('keypress', shortcuts, false);
</script>
"""

with gr.Blocks() as demo:
    action_button = gr.Button(value="Name", elem_id="my_btn")
    textbox = gr.Textbox()
    action_button.click(lambda : "button pressed", None, textbox)
    
demo.launch(head=shortcut_js)

Streaming outputs

In some cases, you may want to stream a sequence of outputs rather than show a single output at once. For example, you might have an image generation model and you want to show the image that is generated at each step, leading up to the final image. Or you might have a chatbot which streams its response one token at a time instead of returning it all at once.

In such cases, you can supply a generator function into Gradio instead of a regular function. Creating generators in Python is very simple: instead of a single return value, a function should yield a series of values instead. Usually the yield statement is put in some kind of loop. Here's an example of an generator that simply counts up to a given number:

def my_generator(x):
    for i in range(x):
        yield i

You supply a generator into Gradio the same way as you would a regular function. For example, here's a a (fake) image generation model that generates noise for several steps before outputting an image using the gr.Interface class:

import gradio as gr
import numpy as np
import time

def fake_diffusion(steps):
    rng = np.random.default_rng()
    for i in range(steps):
        time.sleep(1)
        image = rng.random(size=(600, 600, 3))
        yield image
    image = np.ones((1000,1000,3), np.uint8)
    image[:] = [255, 124, 0]
    yield image

demo = gr.Interface(fake_diffusion,
                    inputs=gr.Slider(1, 10, 3, step=1),
                    outputs="image",
                    api_name="predict")

demo.launch()

Note that we've added a time.sleep(1) in the iterator to create an artificial pause between steps so that you are able to observe the steps of the iterator (in a real image generation model, this probably wouldn't be necessary).

Similarly, Gradio can handle streaming inputs, e.g. an image generation model that reruns every time a user types a letter in a textbox. This is covered in more details in our guide on building reactive Interfaces.

Streaming Media

Gradio can stream audio and video directly from your generator function. This lets your user hear your audio or see your video nearly as soon as it's yielded by your function. All you have to do is

  1. Set streaming=True in your gr.Audio or gr.Video output component.
  2. Write a python generator that yields the next "chunk" of audio or video.
  3. Set autoplay=True so that the media starts playing automatically.

For audio, the next "chunk" can be either an .mp3 or .wav file or a bytes sequence of audio. For video, the next "chunk" has to be either .mp4 file or a file with h.264 codec with a .ts extension. For smooth playback, make sure chunks are consistent lengths and larger than 1 second.

We'll finish with some simple examples illustrating these points.

Streaming Audio

import gradio as gr
from time import sleep

def keep_repeating(audio_file):
    for _ in range(10):
        sleep(0.5)
        yield audio_file

gr.Interface(keep_repeating,
             gr.Audio(sources=["microphone"], type="filepath"),
             gr.Audio(streaming=True, autoplay=True)
).launch()

Streaming Video

import gradio as gr
from time import sleep

def keep_repeating(video_file):
    for _ in range(10):
        sleep(0.5)
        yield video_file

gr.Interface(keep_repeating,
             gr.Video(sources=["webcam"], format="mp4"),
             gr.Video(streaming=True, autoplay=True)
).launch()

End-to-End Examples

For an end-to-end example of streaming media, see the object detection from video guide or the streaming AI-generated audio with transformers guide.

Streaming inputs

        <div class='tip'>
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                <path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/>
                <path d="M9 18h6"/>
                <path d="M10 22h4"/>
            </svg>
            <div><p>Check out <a href="https://fastrtc.org/">FastRTC</a>, our companion library for building low latency streaming web apps with a familiar Gradio syntax. </p></div>
        </div>
            

In the previous guide, we covered how to stream a sequence of outputs from an event handler. Gradio also allows you to stream images from a user's camera or audio chunks from their microphone into your event handler. This can be used to create real-time object detection apps or conversational chat applications with Gradio.

Currently, the gr.Image and the gr.Audio components support input streaming via the stream event. Let's create the simplest streaming app possible, which simply returns the webcam stream un

… [truncated — open the raw llms.txt above for the full file]

Related

Anthropic is an AI safety and research company that's working to build reliable, interpretable, and steerable AI systems.

/llms.txt
15,391 tokens
AI & Machine Learning

Perplexity AI is an AI-powered search engine that provides direct answers to user queries by leveraging large language models.

/llms.txt
1,173 tokens
/llms-full.txt
40,087 tokens
AI & Machine Learning

Shop Dell's laptops, Monitors, Computers, Storage Solutions &amp; Servers for your home and business. Buy online!

/llms.txt
8,533 tokens
AI & Machine Learning

The AI Code Editor

/llms.txt
4,643 tokens
/llms-full.txt
95,589 tokens
AI & Machine Learning

Create the most realistic speech with our AI audio in 1000s of voices and 32 languages. Pioneering research in Text to Speech and AI Voice Generation

/llms.txt
23,168 tokens
/llms-full.txt
1,020,683 tokens
AI & Machine Learning

Get started with the Model Context Protocol (MCP).

/llms.txt
3,315 tokens
/llms-full.txt
223,365 tokens
AI & Machine Learning

The official Python client for the Huggingface Hub.

/llms.txt
143,619 tokens
AI & Machine Learning

The Voice AI Platform: TTS Models, Voice Agents, & More.

/llms.txt
1,738 tokens
/llms-full.txt
56,923 tokens
AI & Machine Learning