Official Python client for the FluidGhost API — spoof a photo, video, or carousel with your API key and get back distinct variants with device-authentic metadata.
Project description
fluidghost
Official Python client for the FluidGhost API.
FluidGhost turns one photo or video into a set of distinct variants — each a fresh, standalone capture with its own metadata, its own pixels, and a device-authentic filename. This SDK does one thing: spoof media with your API key, over the submit → poll → download loop. It handles a single photo, a video, or a whole carousel.
- Full API docs: https://ghost.fluidvip.com/app/docs/
- Python 3.8+ (depends on
requests).
Install
pip install fluidghost
Authentication
Mint an API key in the dashboard (Settings → API keys at https://ghost.fluidvip.com). Keep it server-side — never ship it in client code. An API key is spoof-only: it can submit jobs and read/download their results, and nothing else.
Spoof a photo or video
run() submits a job and waits for it to finish. Results are one-time links:
download_variant() streams the bytes and the object is deleted on a successful download
(a second call raises FluidGhostError with status 410). Photos and videos both go
through the same call — the type is detected from the file.
import os
from fluidghost import FluidGhost
fg = FluidGhost(api_key=os.environ["FLUIDGHOST_KEY"])
job = fg.run(
image="photo.jpg", # or a video: "clip.mp4"
recipe_id="full-refresh",
copies=3,
options={"noise": 35, "ultraSafe": True},
on_poll=lambda j: print(j["status"], j.get("progress")),
)
for v in job["variants"]:
if v["status"] != "completed":
continue
data = fg.download_variant(job["jobId"], v["index"])
with open(v.get("fileName") or f"variant-{v['index']}.jpg", "wb") as f:
f.write(data)
print(v.get("fileName"), "risk", v.get("detectionRisk"), v.get("riskBand"))
You can pass in-memory bytes instead of a path with a (filename, bytes) tuple:
fg.create_job(image=("photo.jpg", my_bytes), recipe_id="full-refresh")
Spoof a carousel (matched set)
A carousel is a set of photos posted together. spoof_carousel() submits one linked job
per file — sharing a session and a running filename sequence so the outputs read as one
cohesive post — and waits for all of them.
jobs = fg.spoof_carousel(
["slide1.jpg", "slide2.jpg", "slide3.jpg"],
recipe_id="full-refresh",
)
for job in jobs:
v = job["variants"][0]
data = fg.download_variant(job["jobId"], v["index"])
with open(v["fileName"], "wb") as f:
f.write(data)
For a fully cohesive set (the same device across every slide), pass a
recipe_configorpreset_idthat pins a device — otherwise each slide picks its own device family.
Settings
Provide exactly one recipe source (or bind a default preset to your key and omit all three):
| Argument | Meaning |
|---|---|
recipe_id |
A bundled starter, e.g. "full-refresh". |
preset_id |
A saved preset created in the dashboard (e.g. "sys:full-refresh"). |
recipe_config |
A full recipe graph (advanced). |
copies |
Number of variants, 1–50. |
strength |
Global strength 0–100. |
options |
Extra knobs merged onto the recipe, e.g. {"noise": 35, "ultraSafe": True}. |
Errors
Every non-2xx response raises FluidGhostError, mirroring the API's {error, message, details}:
from fluidghost import FluidGhost, FluidGhostError
try:
fg.run(image="photo.jpg", recipe_id="full-refresh", copies=3)
except FluidGhostError as e:
print(e.status, e.code, e.details)
if e.code == "rate_limited":
time.sleep(e.retry_after or 5)
if e.code == "insufficient_balance":
... # top up in the dashboard
Configuration
FluidGhost(
api_key="fg_sk_live_…",
base_url="https://api-ghost.fluidvip.com", # default; override for a proxy
timeout=60.0,
)
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fluidghost-2.0.0.tar.gz.
File metadata
- Download URL: fluidghost-2.0.0.tar.gz
- Upload date:
- Size: 7.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d01ec3140e8f7e93d225b13171b290a61cbc4125790cb7e614e225ca475af42e
|
|
| MD5 |
ef6a4530d5c8ba11dfb18cc0c7f6bbdc
|
|
| BLAKE2b-256 |
9a93bc2eb9f1bc6e922aa40f5504140a8372d841677306cc6f7842a20f07dfda
|
File details
Details for the file fluidghost-2.0.0-py3-none-any.whl.
File metadata
- Download URL: fluidghost-2.0.0-py3-none-any.whl
- Upload date:
- Size: 7.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56ed6e19f42d95426628914c9ae6560bcea78445a6bb0a1662df99f2ba335e23
|
|
| MD5 |
a7ffeea88d6bdf4b0bfcaf9b0caa9cca
|
|
| BLAKE2b-256 |
6cdb612abff4eaa7ae54419f60f7f0cab2c003063ab0ddfdd9fa4b839a395a82
|