# Gradio turns one Python function into a web form and a public link

> Gradio builds a web interface from a Python function signature, and the same object can serve a named API endpoint or a shared public URL. The interface is a ten-line file. The sharing flag is where a security review starts.

**gradio-app/gradio** — Build and share delightful machine learning apps, all in Python. 🌟 Star to support our work!

- Repository: https://github.com/gradio-app/gradio
- Website: http://www.gradio.app
- Stars: 43,626 · Forks: 3,615
- Language: Python
- License: Apache-2.0
- Published: 2026-08-08 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/gradio-app-gradio

## gr.Interface pairs one component with one argument, in order

Everything starts with the shape of the function you already have. `gr.Interface` takes `fn`, `inputs`, and `outputs`, and the pairing is positional: one input component per argument, one output component per return value, in the same order.

```python
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()
```

`greet` returns a single string, so `outputs` holds one component. Return a three-item tuple and you owe three output components, and reorder that tuple and the mapping follows the new order, because position is all the wrapper has to go on. A refactor that renames a return field without touching `outputs` produces a form whose boxes are silently paired with the wrong values.

Component names can be written as strings (`"textbox"`) or constructed (`gr.Textbox()`), and the set covers more than 30 built-in components aimed at model work, among them `gr.Textbox()`, `gr.Image()`, and `gr.HTML()`. The cost of that convenience is that the UI is derived rather than written, so you give up direct control over layout and markup in exchange for never touching JavaScript.

## pip install --upgrade gradio brings FastAPI, uvicorn and pandas along

Installation is one command, and the prerequisite is Python 3.10 or higher.

```bash
pip install --upgrade gradio
```

Putting it in a virtual environment is advised, and `requirements.txt` shows why. Installing Gradio means installing a web server and a data stack in the same step: `fastapi>=0.115.2,<1.0`, `starlette>=1.0.1,<2.0`, `uvicorn>=0.14.0`, `huggingface_hub>=1.16.0,<3.0`, `numpy>=1.0,<3.0`, `pandas>=1.0,<4.0`, and `pillow>=8.0,<13.0`. None of it is optional once the form has to be served over HTTP.

The upper bounds sit close to current major versions, so an environment that already carries a newer build of any one of them has to give way when the install runs. `pyproject.toml` classifies support for Python 3.10 through 3.13 and marks the project `Development Status :: 5 - Production/Stable`, which is the project's own statement about its own release maturity rather than an outside assessment.

## gradio app.py replaces python at the terminal and reloads on save

Save that first example as `app.py` and start it with the interpreter.

```bash
python app.py
```

Running from a file opens the demo in a browser at `http://localhost:7860`. Run the same code in a Jupyter notebook or Google Colab and it embeds in the notebook instead, with no port to remember. During local development you can swap the interpreter for the CLI and get reload on save, plus an in-browser chat for writing or editing the app in natural language:

```bash
gradio app.py
gradio --vibe app.py
```

Both come from the console entry point declared in `pyproject.toml`, where the `gradio` script maps to `gradio.cli:cli`. A second script, `upload_theme`, maps to `gradio.themes.upload_theme:main`, which is how a theme reaches a published demo. What the reader should see on port 7860 is the greet form, and after an edit to `app.py` the same form without a manual restart.

## api_name gives the Interface a named HTTP endpoint

The `api_name="predict"` argument in that first example does more than label a button. The Interface is not only a rendered page. It is a server endpoint with a stable, callable name, and the quickstart treats rendering and calling as one system rather than two features.

The consequence is that a function written to be looked at has become something that can be invoked over the network by anything able to reach the port. While the process is up, `http://localhost:7860` keeps that surface on your own machine. The quickstart does not cover a login, an API key, a token parameter, or per-user session isolation for the endpoint. The repository root does carry a `requirements-oauth.txt`, so authentication exists somewhere in the codebase, but nothing in the documented path from install to `launch()` hands you a credential. A team that only meant to show a colleague a form should read that before binding the port to anything wider than loopback.

## share=True keeps the compute on your laptop and the door open

One argument in `launch()` turns the same demo into a public URL, and the address has the shape `https://a23dsf231adb.gradio.live`. The documentation states that anyone around the world can then try the demo from a browser, while the model and all computation continue to run locally on your computer.

Those two halves belong in one sentence. The tunnel does not move your model onto someone else's hardware. It points a public address at the laptop that is already running it, and the documented flag accepts no credential and no allowlist. Who can run your function is decided by who receives the link, and what they can run is whatever `fn` does with the files and compute on that machine. Stopping exposure means stopping the process, because nothing in the documented sharing path lets you revoke one link without taking the whole demo down. Sharing is the reason many people adopt Gradio, and it is also the decision that needs a second reader.

## gradio_client==2.7.1 is an exact pin, and both release trains move

Upgrading is not a single knob. `requirements.txt` pins `gradio_client==2.7.1` with no range at all, while `huggingface_hub` is free anywhere inside `>=1.16.0,<3.0`. The client cannot be moved on its own, and anything in your environment that expected a different one has it rewritten at install time.

Both sides of the repository version quickly and separately. The last push was on 2026-09-25. On 2026-09-29 the release list shows `gradio@6.29.0` next to `@gradio/video@0.23.2` and `@gradio/uploadbutton@0.11.0`, so the Python package and the frontend component packages run on independent counters. The directories behind that split sit at the repository root: `js/`, `client/`, `patches/`, `.changeset/`, `pnpm-workspace.yaml`, and a root `package.json` named `gradio-ui` whose development script is `pnpm css && pnpm --filter @gradio/preview build && pnpm --filter @self/app dev`.

That last detail is the cost people miss. A one-line change to a Python file is small. A change to how a component renders is a pnpm job, and the root `build` script allocates an 8 GB Node heap through `--max-old-space-size=8192` before it compiles. Budget for a JavaScript toolchain even when your edit is on the Python side.

## audioop-lts<=0.2.2 exists because Python 3.13 deleted audioop

Audio on a recent interpreter depends on a backport. `requirements.txt` carries `audioop-lts<=0.2.2; python_version >= "3.13"` with a comment saying it replaces the built-in `audioop` module removed in Python 3.13 and is required by `pydub`. Read that line as a ceiling, not a preference. An audio component running on 3.13 is calling into a third-party shim that will not go past 0.2.2, so when a future `pydub` or Python point release needs a newer one, the install fails rather than degrading to a working subset.

The package metadata stops at the same boundary. The `classifiers` in `pyproject.toml` declare Python 3.10, 3.11, 3.12, and 3.13, so a 3.14 interpreter sits outside what the project advertises, even though `requires-python` only sets a floor of `>=3.10`. Anyone standardising on the newest interpreter should confirm which audio path they are on before committing to it, because the shim only exists for interpreters where the standard library module is gone.

## Gradio generates the form; Streamlit reruns the script

Streamlit is the name people search alongside Gradio, and the documentation never makes that comparison. The difference sits in where control flow lives. Gradio takes a function you have already written, reads its shape through `fn`, `inputs`, and `outputs`, and generates a form whose fields are the arguments. Streamlit executes a script you wrote top to bottom and re-runs it on every interaction, so widget order, branching, and state transitions live in your Python rather than in a generated description of a signature.

What follows from that is where each one fits. Gradio's component set is built around model input and output, more than 30 components including `gr.Textbox()`, `gr.Image()`, and `gr.HTML()`, and the example apps under `demo/` are named after model jobs such as `demo/asr/`, `demo/agent_chatbot/`, `demo/audio_component/`, and `demo/blocks_chained_events/`. An app that is a sequence of steps mutating a table reads more naturally as a Streamlit script. An app that is one model call with a handful of typed parameters, reachable today, is the shorter path through `demo.launch()` in a file.

## Conclusion

Gradio fits a Python developer who has one function and needs a reachable form quickly: the 3.10 floor, one pip command, and thirty-plus model components cover the common case without any frontend work. It does not fit a team that needs sign-in, per-user sessions, or a stable public endpoint, because the quickstart path offers a form, an api_name, and share=True and says nothing about access control. Check two things before adopting it. First, whether the exact pin gradio_client==2.7.1 in requirements.txt collides with what your environment already holds. Second, whether your function is safe for any stranger who receives a link, since share=True keeps the computation on your own machine.

## FAQ

### What is Gradio used for?

Gradio builds a web interface around a machine learning model, an API, or any arbitrary Python function, then shares a link to it in a few seconds. The project states that no JavaScript, CSS, or web hosting experience is required.

### Is Gradio a Python library?

Yes. The distribution name is `gradio`, the primary language is Python, and `pyproject.toml` sets `requires-python = ">=3.10"` under the Apache-2.0 license.

### How to install Gradio?

The documented command is `pip install --upgrade gradio`, and Python 3.10 or higher is the stated prerequisite. The project advises installing it inside a virtual environment, with per-operating-system instructions on its own site.

### How to use Gradio in Python?

Define a function, hand it to `gr.Interface` with `fn`, `inputs`, and `outputs`, then call `demo.launch()`. A file named `app.py` is started with `python app.py` and the demo opens at `http://localhost:7860`.

### Is Gradio better than Streamlit?

The project does not make that comparison, so the difference is structural. Gradio generates a form from a function signature using more than 30 built-in components, while Streamlit re-runs a script you write in order. Neither is presented as the winner.

### How to use Gradio in Colab?

The project says you can run Gradio in a code editor, a Jupyter notebook, Google Colab, or anywhere else you write Python. In a notebook the demo appears embedded in the notebook rather than opening at `http://localhost:7860`.

## Sources

- [Official documentation](http://www.gradio.app)
- [Official README](https://github.com/gradio-app/gradio#readme)
- [Project repository](https://github.com/gradio-app/gradio)
- [Release notes](https://github.com/gradio-app/gradio/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gradio-app-gradio
