A newer version of the Gradio SDK is available: 6.22.0
πͺ API Reference β ID Photo Retoucher
Base URL: https://esmailx51-retoucher.hf.space
Gradio API Prefix: /gradio_api
API Endpoint: /gradio_api/run/retouch
Interactive Docs: View on Hugging Face
Overview
The retoucher exposes its interface and programmatic prediction endpoints through Gradio.
Hugging Face Spaces Queue Requirement (Gradio 5):
Since this Space runs on ZeroGPU with queueing enabled, direct stateless HTTPPOSTrequests (using rawrequestsorcURL) to the/gradio_api/run/retouchendpoint are blocked with a404 Not Founderror ("This API endpoint does not accept direct HTTP POST requests. Please join the queue to use this API.").To consume the API programmatically, you must use the official client libraries (
gradio_clientin Python or@gradio/clientin JavaScript/TypeScript) as shown in Section 1 and Section 3. The clients automatically handle the SSE queue handshake and state tracking. Raw HTTP/cURL calls will only work in local development environments where the queue is disabled.
| Field | Value |
|---|---|
| Endpoint (Local/No Queue) | POST /gradio_api/run/retouch |
| Upload Endpoint (Local/No Queue) | POST /gradio_api/upload |
| Queue | Enabled (requests are queued) |
| GPU | ZeroGPU A10G (allocated on-demand per request) |
| Max File Size | No limit |
| Cold Start | ~30β60s (first request after idle downloads model weights) |
Parameters
| # | Name | Type | Default | Range | Description |
|---|---|---|---|---|---|
| 1 | image |
Image |
required | β | Input face photo (file path, URL, or base64) |
| 2 | strength |
float |
0.6 |
0.0 β 1.0 |
Skin retouching intensity. 0 = no change, 1 = full GFPGAN restoration |
| 3 | undereye_strength |
float |
0.5 |
0.0 β 1.0 |
Under-eye correction intensity. 0 = no correction, 1 = maximum brightening |
| 4 | crease_strength |
float |
0.4 |
0.0 β 1.0 |
Crease/sag softening. Softens smile lines, marionette folds, double chins |
| 5 | jaw_tighten |
float |
0.3 |
0.0 β 1.0 |
Jawline tightening. Gently warps/lifts sagging jowls inward |
| 6 | show_masks |
bool |
false |
β | If true, returns a debug visualization with mask overlays |
Returns
| # | Name | Type | Description |
|---|---|---|---|
| 1 | retouched_image |
Image |
The retouched face photo |
| 2 | debug_image |
Image | null |
Debug visualization (only if show_masks=true). Green = skin, Orange = under-eye, Blue = wrinkle zones |
Usage Examples
1. Python β Gradio Client (Recommended)
The easiest way. Install with pip install gradio_client.
from gradio_client import Client
# Connect to the Space
client = Client("esmailx51/retoucher")
# Basic usage β just retouch with defaults
result = client.predict(
"photo.jpg", # local file path
0.6, # skin strength
0.5, # undereye strength
0.4, # crease strength
0.3, # jaw tighten
False, # show debug masks
api_name="/retouch"
)
retouched_path = result[0] # path to the retouched image
debug_path = result[1] # None (since show_masks=False)
print(f"Retouched image saved to: {retouched_path}")
From a URL instead of a local file
from gradio_client import Client, handle_file
client = Client("esmailx51/retoucher")
result = client.predict(
handle_file("https://example.com/face.jpg"),
0.7, 0.5, 0.4, 0.3, False,
api_name="/retouch"
)
Aggressive retouching (older subjects)
result = client.predict(
"photo.jpg",
0.8, # strong skin smoothing
0.7, # strong undereye correction
0.7, # strong wrinkle reduction
0.5, # strong jaw tightening
False,
api_name="/retouch"
)
Minimal retouching (young subjects)
result = client.predict(
"photo.jpg",
0.3, # light skin smoothing
0.2, # light undereye
0.1, # minimal wrinkle reduction
0.0, # no jaw tightening
False,
api_name="/retouch"
)
With debug masks
result = client.predict(
"photo.jpg",
0.6, 0.5, 0.4, 0.3,
True, # show debug masks
api_name="/retouch"
)
retouched = result[0]
debug_vis = result[1] # side-by-side: masks overlay | retouched result
2. Python β requests (Raw HTTP)
Local/No-Queue only: This raw HTTP request method will return a
404 / Please join the queueerror on the hosted Hugging Face Space. It only works in local development environments where the Gradio queue is disabled. For hosted Spaces, you must use thegradio_clientlibrary (Section 1).
import requests
import json
from pathlib import Path
# In Gradio 5, endpoints are prefixed with /gradio_api
BASE_URL = "http://127.0.0.1:7860/gradio_api"
# Step 1: Upload the image to the local Gradio server
with open("photo.jpg", "rb") as f:
upload_resp = requests.post(
f"{BASE_URL}/upload",
files={"files": ("photo.jpg", f, "image/jpeg")}
)
uploaded_files = upload_resp.json()
file_path = uploaded_files[0] # server-side temp path
# Step 2: Call the local API prediction endpoint (/run/retouch)
payload = {
"data": [
{"path": file_path, "meta": {"_type": "gradio.FileData"}},
0.6, # skin strength
0.5, # undereye strength
0.4, # crease strength
0.3, # jaw tighten
False # show masks
]
}
resp = requests.post(f"{BASE_URL}/run/retouch", json=payload)
result = resp.json()
# Step 3: Extract & download the result
# In Gradio 5, the direct response maps outputs to keys like "output" (or "data" fallback)
if "data" in result:
retouched_url = result["data"][0]["url"]
else:
retouched_url = result["output"]["url"]
img_data = requests.get(retouched_url).content
Path("retouched.jpg").write_bytes(img_data)
print("Saved retouched.jpg")
3. JavaScript / TypeScript
Install with npm install @gradio/client.
import { Client } from "@gradio/client";
const client = await Client.connect("esmailx51/retoucher");
const result = await client.predict("/retouch", {
image: "https://example.com/face.jpg", // URL or Blob
strength: 0.6,
undereye_strength: 0.5,
crease_strength: 0.4,
jaw_tighten: 0.3,
show_masks: false,
});
console.log(result.data);
// [{ url: "https://...retouched.webp", ... }, null]
With a local file (Node.js)
import { Client, handle_file } from "@gradio/client";
import fs from "fs";
const client = await Client.connect("esmailx51/retoucher");
const result = await client.predict("/retouch", {
image: handle_file("./photo.jpg"),
strength: 0.6,
undereye_strength: 0.5,
crease_strength: 0.4,
jaw_tighten: 0.3,
show_masks: false,
});
// Download the retouched image
const imageUrl = result.data[0].url;
const response = await fetch(imageUrl);
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync("retouched.jpg", buffer);
Browser (Fetch from a file input)
import { Client } from "@gradio/client";
async function retouchPhoto(fileInput) {
const client = await Client.connect("esmailx51/retoucher");
const file = fileInput.files[0];
const result = await client.predict("/retouch", {
image: new Blob([await file.arrayBuffer()], { type: file.type }),
strength: 0.6,
undereye_strength: 0.5,
crease_strength: 0.4,
jaw_tighten: 0.3,
show_masks: false,
});
// Display the result
const imgUrl = result.data[0].url;
document.getElementById("result").src = imgUrl;
}
4. cURL
Local/No-Queue only: This cURL method will return a
404 / Please join the queueerror on the hosted Hugging Face Space. It only works in local development environments where the Gradio queue is disabled. For hosted Spaces, you must use the official client libraries (Section 1 & 3).
# Step 1: Upload the image (pointing to local Gradio 5 API prefix)
FILE_PATH=$(curl -s -X POST \
"http://127.0.0.1:7860/gradio_api/upload" \
-F "files=@photo.jpg" \
| jq -r '.[0]')
# Step 2: Call the API prediction endpoint
curl -s -X POST \
"http://127.0.0.1:7860/gradio_api/run/retouch" \
-H "Content-Type: application/json" \
-d "{
\"data\": [
{\"path\": \"$FILE_PATH\", \"meta\": {\"_type\": \"gradio.FileData\"}},
0.6,
0.5,
0.4,
0.3,
false
]
}" | jq -r '.output.url'
Batch Processing (Python)
Process multiple images in sequence:
from gradio_client import Client
from pathlib import Path
client = Client("esmailx51/retoucher")
input_dir = Path("./input_photos")
output_dir = Path("./retouched")
output_dir.mkdir(exist_ok=True)
for img_path in input_dir.glob("*.jpg"):
print(f"Processing {img_path.name}...")
result = client.predict(
str(img_path),
0.6, 0.5, 0.4, 0.3, False,
api_name="/retouch"
)
# Copy result to output directory
retouched = Path(result[0])
retouched.rename(output_dir / img_path.name)
print(f" β Saved to {output_dir / img_path.name}")
Integration Example: Flask Backend
from flask import Flask, request, send_file
from gradio_client import Client
import tempfile, shutil
app = Flask(__name__)
gr_client = Client("esmailx51/retoucher")
@app.route("/retouch", methods=["POST"])
def retouch():
# Save uploaded file
photo = request.files["photo"]
strength = float(request.form.get("strength", 0.6))
undereye = float(request.form.get("undereye", 0.5))
creases = float(request.form.get("creases", 0.4))
jaw = float(request.form.get("jaw", 0.3))
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp:
photo.save(tmp.name)
result = gr_client.predict(
tmp.name,
strength, undereye, creases, jaw, False,
api_name="/retouch"
)
return send_file(result[0], mimetype="image/webp")
if __name__ == "__main__":
app.run(port=5000)
Error Handling
from gradio_client import Client
from gradio_client.exceptions import AppError
client = Client("esmailx51/retoucher")
try:
result = client.predict(
"photo.jpg", 0.6, 0.5, 0.4, 0.3, False,
api_name="/retouch"
)
except AppError as e:
if "No face detected" in str(e):
print("No face found in the image")
elif "queue is full" in str(e):
print("Server is busy, try again later")
else:
print(f"API error: {e}")
except ConnectionError:
print("Space is sleeping β the first request wakes it up (~60s)")
Tuning Guide
| Goal | strength | undereye | creases | jaw |
|---|---|---|---|---|
| Natural / Minimal | 0.3 | 0.2 | 0.1 | 0.0 |
| Balanced (default) | 0.6 | 0.5 | 0.4 | 0.3 |
| Aggressive (older subjects) | 0.8 | 0.7 | 0.7 | 0.5 |
| Skin only (no anti-aging) | 0.6 | 0.0 | 0.0 | 0.0 |
| Under-eye only | 0.0 | 0.7 | 0.0 | 0.0 |
Rate Limits & Notes
- Cold start: If the Space has been idle, the first request takes
30β60 seconds (model download + loading). Subsequent requests are fast (5β10s on GPU). - Queue: Requests are queued. If the Space is busy, your request will wait in line.
- GPU timeout: ZeroGPU allocates GPU per-request. Very large images may time out.
- Output format: Retouched images are returned as PNG by default to maintain high-resolution lossless quality.
- No face detected: If no face is found, the original image is returned unchanged.