Runtime

How to run a Gradio demo in a sandbox instead of a share link

Build Gradio and your app into an image whose start command runs it on port 7860, create a sandbox from it, and share 7860 as a preview.

On Runtime the demo's address lasts as long as you keep the sandbox, and it can be private. A Gradio share link expires after a week and is open to anyone who has it. A Runtime preview is refused without its token unless you make it public, stays up for as long as you keep the sandbox, and on a paid account can sit at your own domain. Gradio 6.28.0 was current on 25 September 2026.

Question share=True Runtime preview
Where the app runs Your machine, or wherever launch() runs A Firecracker microVM of its own
How long the link lasts Expires after 1 week For as long as the sandbox and its preview exist
Who can open it Anyone with the link Token holders by default, or anyone when public
Traffic goes through Gradio's share servers, as a proxy Runtime's preview edge

Build the demo into an image

An image can say what a sandbox runs when it starts and when it counts as ready. With readyPort: 7860, the create call answers once Gradio is listening, so the link works the moment you have it:

dockerfileFROM runtimeENV GRADIO_ANALYTICS_ENABLED=FalseRUN pip install --no-cache-dir gradio==6.28.0COPY app.py /workspace/app.pyRUN chown 1000:1000 /workspace/app.py
TypeScriptimport { readFile } from "node:fs/promises";import { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build(  {    name: "shout-demo",    dockerfile: await readFile("demo/Dockerfile", "utf8"),    contextDir: "demo",    start: { command: "python3 /workspace/app.py", readyPort: 7860, readyTimeoutSeconds: 120 },  },  { onLog: (line) => console.log(line.text) },);const sbx = await runtime.sandboxes.create({ image: "shout-demo", timeoutSeconds: 3600 });console.log(sbx.info.start); // { state: "ready", ... } once Gradio listensconst preview = await sbx.previews.create(7860);console.log(preview.urlWithToken);
Pythonfrom withruntime import Runtimeruntime = Runtime()with open("demo/Dockerfile") as handle:    runtime.images.build(        name="shout-demo",        dockerfile=handle.read(),        context_dir="demo",        start={"command": "python3 /workspace/app.py", "ready_port": 7860, "ready_timeout_seconds": 120},    )sbx = runtime.sandboxes.create(image="shout-demo", timeout_seconds=3600)print(sbx.info["start"])print(sbx.previews.create(7860)["urlWithToken"])

The app itself is ordinary Gradio, with launch() and no share:

Pythonimport gradio as grdef shout(text: str) -> str:    return text.upper()demo = gr.Interface(fn=shout, inputs="text", outputs="text")demo.launch()

Gradio listens on 127.0.0.1:7860 by default, which a preview reaches from inside the sandbox. GRADIO_SERVER_PORT moves the port, and GRADIO_ANALYTICS_ENABLED=False in the image stops Gradio's analytics.

Call the demo from code

Every Gradio app has an HTTP API as well as its page. A private preview takes the token as a header, so a test or an agent can call the demo directly. The endpoint is named after the function: shout here.

TypeScriptimport { Sandbox } from "withruntime";const sbx = await Sandbox.connect(process.env.SANDBOX_ID ?? "");const preview = await sbx.previews.create(7860);const headers = { "x-runtime-preview-token": preview.token!, "content-type": "application/json" };const queued = await fetch(new URL("gradio_api/call/shout", preview.url), {  method: "POST",  headers,  body: JSON.stringify({ data: ["hello"] }),});const { event_id } = (await queued.json()) as { event_id: string };const result = await fetch(new URL(`gradio_api/call/shout/${event_id}`, preview.url), { headers });console.log(await result.text()); // event: complete / data: ["HELLO"]

The first call queues the request and answers with an event_id; the second streams the result as server-sent events. In a test on 25 September 2026, Gradio 6.28.0 answered data: ["HI"] for the input hi.

Make it public, or keep it to reviewers

Want Do
Only you Open urlWithToken once in your browser
A reviewer Send them a fresh urlWithToken
Anyone previews.create(7860, { visibility: "public" })
Cut off every link handed out so far previews.rotate(7860)
A login inside the app as well demo.launch(auth=("admin", password))
Your own hostname A custom domain on a paid account (networking)

Models and memory

A demo that loads a model at start needs the memory for it and the disk for its files. Ask for them at create, memoryMiB and diskMiB, and give the image's ready check time with readyTimeoutSeconds, which goes up to 300. For Hugging Face models on CPU, see Transformers in a sandbox.

A sandbox's lease runs for its timeoutSeconds, at most an hour ahead, and then pauses it with the app still in memory. extend moves the lease, and a visit to the preview wakes a paused sandbox with a short "Waking up" page.

Sources

Checked 25 September 2026.

  • Sharing your app: share links expire after 1 week, the share servers act as a proxy, and auth=
  • Gradio environment variables: GRADIO_SERVER_PORT (7860), GRADIO_SERVER_NAME (127.0.0.1), GRADIO_ANALYTICS_ENABLED
  • gradio on PyPI: version 6.28.0, Python 3.10 or later
  • A local test of Gradio 6.28.0 on 25 September 2026: POST /gradio_api/call/shout returned an event_id, and GET /gradio_api/call/shout/<event_id> returned event: complete with data: ["HI"]

Facts on this page were checked on 25 September 2026.