The gap between “I have a working model in a notebook” and “someone else can try it” is where most interesting research quietly dies. A notebook is not something you can send to a curator, a collaborator, a residency panel or a client. Building a web app to wrap it is a different project with different skills, and it usually doesn’t happen.
Gradio collapses that gap to about five lines of Python.
What it is
An open-source Python library that generates an interactive web interface for a function. You describe the inputs and outputs; it builds the UI, runs a server, and optionally gives you a public URL that works from anyone’s browser. You write no HTML, CSS or JavaScript.
It requires Python 3.10 or higher.
pip install gradio
The five-line version
import gradio as gr
def greet(name):
return "Hello " + name + "!"
demo = gr.Interface(fn=greet, inputs="text", outputs="text")
demo.launch()
Run that and a browser opens with a text box, a submit button and an output panel.
gr.Interface takes a function, an input component and an output component. The string shortcuts ("text", "image", "audio", "video", "number", "slider") cover most cases, and swapping them is how you go from a toy to something real:
demo = gr.Interface(
fn=stylise,
inputs=[gr.Image(type="pil"), gr.Slider(0, 1, value=0.7, label="Strength")],
outputs=gr.Image(),
title="Style transfer",
description="Upload an image.",
examples=[["examples/portrait.jpg", 0.7]],
)
Note examples. Providing two or three pre-loaded inputs is the single highest-value thing you can add, because the most common failure of a shared demo is that the visitor doesn’t know what to put in and leaves.
When Interface runs out: Blocks
gr.Interface assumes one function, inputs on the left, outputs on the right. Real tools need more than that — multiple steps, conditional behaviour, state between actions. That’s gr.Blocks, a lower-level API for custom layouts and data flow.
with gr.Blocks() as demo:
gr.Markdown("## Two-stage generator")
with gr.Row():
prompt = gr.Textbox(label="Prompt")
seed = gr.Number(value=0, label="Seed")
generate = gr.Button("Generate", variant="primary")
gallery = gr.Gallery()
upscale = gr.Button("Upscale selected")
final = gr.Image()
generate.click(fn=make_images, inputs=[prompt, seed], outputs=gallery)
upscale.click(fn=upscale_image, inputs=gallery, outputs=final)
demo.launch()
Row and Column handle layout, .click() wires an event to a function, and any component can be both an output of one step and an input to the next. That’s enough structure for most research demos.
The share link, and what it actually is
demo.launch(share=True)
This prints a public *.gradio.live URL that anyone can open. It is genuinely useful and genuinely misunderstood, so be clear on the mechanics:
- The link tunnels to the machine you’re running on. Your laptop is the server.
- It expires (72 hours), and dies the moment you stop the process or close the laptop.
- Everyone using it is queueing for your GPU.
That makes it excellent for hackathons, a quick look from a collaborator, a client preview, or a demo in a talk. It is not hosting. Do not put it in a grant application as a permanent link.
Making it permanent
For something that outlives your terminal session, push the same code to a Hugging Face Space. A Space is a Git repo containing your app.py and a requirements.txt; Hugging Face runs it and gives you a stable URL. The free CPU tier is real and sufficient for small models; GPU tiers are paid.
The code does not change. The Gradio app you tested locally is the Gradio app that runs in the Space, which is the main reason to start here rather than with a web framework.
Things worth knowing before you rely on it
- It’s single-threaded by default. Use
demo.queue()if more than one person will use it at once, or the second visitor sees it hang. - Cold starts on free hosting are slow. A Space that’s been idle takes time to wake. Warn people, or expect them to assume it’s broken.
- Anything you expose, you expose. A file-upload input on a public link is a file-upload input on a public link. Don’t run untrusted input through anything with filesystem access.
- It works with PyTorch, TensorFlow and Hugging Face Transformers without special handling — Gradio only cares that you hand it a Python function.
Where to go next
Once a demo exists, the useful next steps are gr.State for per-session memory, gr.ChatInterface if you’re wrapping a language model, streaming outputs with yield for progressive results, and gr.Api usage so the same app can be called programmatically as well as clicked.
The broader point: a demo that someone can open and try is worth more than a better model nobody can reach. This is the cheapest way to get there.