Unofficial Python API client for vibes.ai β Meta's AI video creation studio. Generate videos, images, TTS, lip-sync, and more, all from a Python script or CLI.
This package was built by reverse-engineering the vibes.ai Next.js bundles and observing real network traffic. It is not affiliated with, endorsed by, or officially supported by Meta or Vibes.
# 1) Install
pip install VibesAI-api
# 2) Set your cookie (grab from DevTools β Application β Cookies β vibes.ai)
export VIBES_META_SESSION="e60e910a-242a-...-K54E"
# 3) Generate your first video
vibes-api one-shot \
--prompt "A serene mountain landscape at sunset" \
--aspect-ratio 16:9 --resolution 720p --variations 4 \
--download-dir ./outOr in Python:
from vibes_api import VibesClient, AspectRatio, Resolution
client = VibesClient(meta_session="...")
project = client.create_project(name="My Video")
batch = client.generate_video(
project_id=project["id"],
prompt="A serene mountain landscape at sunset",
aspect_ratio=AspectRatio.LANDSCAPE,
resolution=Resolution.P720,
variations=4,
)
client.download_video(batch["content"][0]["id"], "sunset.mp4")| Feature | Method | Notes |
|---|---|---|
| Auth | get_me(), get_system_status(), logout() |
Cookie-based |
| Projects | list_projects(), create_project(), get_project(), update_project(), delete_project(), duplicate_project() |
|
| Video generation (t2v) | generate_video() |
text-to-video, 1-4 variations |
| Image generation (t2i) | generate_image() |
synchronous, returns immediately |
| π₯ Video extend (auto) | auto_extend_video(), extend_video(prompt=None) |
extends a video by ~5s, no directive |
| π₯ Video extend (manual) | manual_extend_video(), extend_video(prompt=...) |
extends with a directive prompt |
| π₯ Video edit (v2v) | edit_video() |
re-render existing video with a directive |
| π₯ Image animate (auto) | auto_animate_image() |
animate a still image with original prompt |
| π₯ Image animate (manual) | manual_animate_image() |
animate with a directive prompt |
| π Regenerate batch | regenerate_batch() |
re-roll with same or new prompt |
| πΌοΈ Image editing | edit_image() |
prompt-driven edits |
| β¨ Prompt enhancement | enhance_prompt() |
returns 4 AI-rewritten variations |
| π£οΈ Lip sync | generate_lipsync() |
image + audio + script β video |
| π TTS | tts(), list_voices(), save_tts_audio() |
41 preset voices |
| π Start/end frame | generate_video(start_frame=..., end_frame=...), build_frame_handle() |
image-to-video with keyframes |
| π§ Ingredients (character/style/scene) | list_characters(), list_styles(), list_scenes(), create_ingredient(), delete_ingredient() |
studio ingredient CRUD |
| π§ Ingredient refs in generation | ingredients=[...], create_ingredients=[...] |
apply or inline-create |
| π¨ Moodboards | list_moodboards(), get_moodboard(), create_moodboard(), delete_moodboard() |
|
| β¬οΈ Uploads | upload_image(), upload_image_file(), upload_video_direct(), upload_audio_direct(), upload_media(), upload_profile_picture() |
|
| π Media library | list_media(), favorite_content_item(), delete_content_item(), delete_content_items() |
|
| β¬οΈ Download | download_video(), download_image() |
|
| π Share links | create_share_link(), list_share_links(), revoke_share_link() |
|
| π΅ Music library | search_music(), lookup_music_thumbnail(), clip_music(), clip_audio() |
|
| π¬ Timeline chat | timeline_chat() |
streaming AI assistant (SSE) |
| π¬ Timeline export | export_timeline(), export_timeline_async(), check_export_status(), cancel_export() |
render composition β MP4 |
| π Real-time sync | get_sync_status(), stream_sync_updates(), stream_batch_updates() |
SSE for collaborative editing |
| π Quota | get_quota_upsell() |
|
| βοΈ Account settings | delete_account(), delete_all_media(), remove_all_posts() |
|
| π Bug reports | report_bug(), record_consent() |
|
| π€ Collaborators | list_collaborators(), remove_collaborator() |
|
| π¦ Project assets | list_project_assets(), add_project_asset(), import_project_assets(), list_available_assets() |
cross-project reuse |
| β³ Batch polling | poll_batch(), list_batches(), list_project_batches(), get_batch(), delete_batch() |
|
| π One-shot | create_video_from_prompt() |
end-to-end convenience |
The vibes-api CLI exposes every feature as a subcommand. Run vibes-api --help for the full list.
# User
vibes-api me
# Projects
vibes-api projects list
vibes-api projects create --name "My Video"
vibes-api projects get <id>
vibes-api projects delete <id> --delete-assets
# Video generation
vibes-api videos generate --project-id <id> --prompt "sunset over ocean" \
--aspect-ratio 16:9 --resolution 720p --variations 4 --download-dir ./out
# π Video extend (auto/manual)
vibes-api videos extend --project-id <id> --batch-id <batch> \
--content-id <content> # auto-extend (no --prompt)
vibes-api videos extend --project-id <id> --batch-id <batch> \
--prompt "camera pans up to reveal the sky" # manual extend
# π Video edit (v2v)
vibes-api videos edit --project-id <id> --batch-id <batch> \
--prompt "change the weather to rain"
# Image generation
vibes-api images generate --project-id <id> --prompt "cyberpunk city"
# π Image animate (auto/manual)
vibes-api images animate --project-id <id> --content-id <content>
vibes-api images animate --project-id <id> --content-id <content> \
--prompt "camera zooms in slowly"
# π Batch regenerate (re-roll)
vibes-api batches regenerate <batch-id> --project-id <id>
vibes-api batches regenerate <batch-id> --project-id <id> --prompt "new prompt"
# π Ingredient CRUD
vibes-api ingredients list [--type CHARACTER|STYLE|SETTING]
vibes-api ingredients create --name "My Character" --type CHARACTER \
--image-ent-id <id> --image-url <url>
vibes-api ingredients delete <ingredient_id>
# TTS
vibes-api voices list
vibes-api tts --voice play_ai_Marisol --text "Hello world" --out hello.mp3
# Media library
vibes-api media list --type video --limit 10
vibes-api media download --id <id> --out video.mp4
vibes-api media delete --ids <id1> <id2>
# Prompt enhancement
vibes-api prompts enhance --prompt "a cat"
# Share links
vibes-api share create --entity-type project --entity-id <id>
vibes-api share list --entity-type project --entity-id <id>
vibes-api share revoke <share_link_id>
# Batches
vibes-api batches list --project-id <id>
vibes-api batches get <batch_id>
vibes-api batches poll <batch_id> --timeout 180
# Music
vibes-api music search --query "lofi"
# Timeline AI chat
vibes-api chat "add a 5 second sunset clip"
# π Real-time sync
vibes-api sync status --entity-type project --entity-id <id>
vibes-api sync stream --entity-type project --entity-id <id> # Ctrl+C to stop
# π Quota
vibes-api quota
# End-to-end one-shot
vibes-api one-shot --prompt "sunset over ocean" --download-dir ./outVibes uses a two-step generation pattern:
1) POST /api/generation-batches β create a batch shell (with client-generated UUID v7)
2) POST /api/generate/videos β trigger actual generation
3) GET /api/generation-batches/{id} β poll until isComplete=true
OR /api/generation-batches/{id}/stream (SSE)
The client abstracts this away behind generate_video() (which polls by default) and generate_image() (which is synchronous).
The server expects batch IDs to be UUID v7 (timestamp-ordered) prefixed with batch- so it can derive the creation time from the high bits AND so that the download endpoint accepts the content IDs. The client generates these internally via _uuid_v7(). Special flows use different prefixes:
batch-<uuid_v7>β normal text/image generationextend-<timestamp>-<random>β video extensionimage2video-<timestamp>-<random>β image-to-video (animate)video2video-<timestamp>-<random>β video-to-video (edit)
Only 3 aspect ratios are supported (verified live):
| Aspect | Image dimensions | Notes |
|---|---|---|
1:1 |
1280Γ1280 | Square |
9:16 |
720Γ1280 | Portrait (UI default) |
16:9 |
1280Γ720 | Landscape |
Resolutions: 480p (default, faster) and 720p (slower but higher quality).
| Type | Default model | Description |
|---|---|---|
| Image | midjen-base |
Standard image generation |
| Video (t2v / i2v) | midjen-short |
~5 second clips |
| Video extend | midjen-extend |
For extending an existing video |
| Video edit (v2v) | midjen-video-edit |
For re-rendering with a directive |
| Lip sync | lipsync / midjen-lipsync-async |
Lip-sync generation |
| Prompt LLM | gemini-2.5-flash |
Used for prompt enhancement |
generationType |
When to use |
|---|---|
t2v |
text β video |
t2i |
text β image |
i2v |
image (start frame) β video |
extend |
extend an existing video |
v2v |
video β video (re-render with directive) |
lipsync |
lip-sync generation |
Vibes supports three ingredient types:
- CHARACTER (UI: "Character") β applies via
orefImageHandleinternally - STYLE (UI: "Style") β applies via
srefImageHandleinternally - SETTING (UI: "Scene") β applies via
settingImageHandlesinternally
There are three ways to reference an ingredient in a generation:
from vibes_api import IngredientType
from vibes_api.ingredients import IngredientRef, CreateIngredient
# 1. By existing ingredient ID (from list_ingredients)
character = IngredientRef.by_id(
ingredient_id="800957099700717",
ingredient_type=IngredientType.CHARACTER,
name="Valdrin",
image_url="https://...",
)
# 2. By uploaded image entity ID (creates a new ingredient on-the-fly)
style = CreateIngredient.by_image_ent_id(
image_ent_id="1177...",
ingredient_type=IngredientType.STYLE,
name="Cyberpunk neon",
image_url="https://...",
)
# 3. By name only (uses prompt-generated image)
scene = CreateIngredient.by_name(
ingredient_type=IngredientType.SETTING,
name="Misty forest at dawn",
)
# Pass them to generate_video
batch = client.generate_video(
project_id=project["id"],
prompt="...",
ingredients=[character], # goes in `ingredients[]`
create_ingredients=[style, scene], # goes in `createIngredients[]`
)You can also CRUD ingredients directly:
client.list_characters(),list_styles(),list_scenes()client.create_ingredient(name, ingredient_type, source_image_ent_id, ...)client.delete_ingredient(ingredient_id)
Generate a video that interpolates between two keyframes:
# Generate the start frame image
start_resp = client.generate_image(
project_id=project["id"],
prompt="a rose in full bloom",
aspect_ratio="16:9",
)
# Generate the end frame image
end_resp = client.generate_image(
project_id=project["id"],
prompt="a withered, dried rose",
aspect_ratio="16:9",
)
# Build frame handles
start_frame = client.build_frame_handle({
"mediaEntId": start_resp["data"][0]["imageEntId"],
"imageUrl": start_resp["data"][0]["url"],
})
end_frame = client.build_frame_handle({
"mediaEntId": end_resp["data"][0]["imageEntId"],
"imageUrl": end_resp["data"][0]["url"],
})
# Generate the video with both keyframes
batch = client.generate_video(
project_id=project["id"],
prompt="the rose slowly wilts, time-lapse effect",
start_frame=start_frame,
end_frame=end_frame,
aspect_ratio="16:9",
)For a single start frame (i2v without end frame), just omit end_frame.
The Vibes UI shows "Auto extend" and "Manual extend" buttons next to each generated video. Both call the same backend β the only difference is whether you supply a directive prompt:
# Get a previously-generated video's full content item
batch = client.get_batch("batch-...")
source_video = batch["content"][0]
# AUTO extend: no prompt, server continues original
extended_auto = client.extend_video(
project_id=project["id"],
source_video=source_video,
)
# MANUAL extend: provide a directive
extended_manual = client.manual_extend_video(
project_id=project["id"],
source_video=source_video,
prompt="camera pans up to reveal the sky",
)The source_video dict must be the full content item (not just an ID) because extend needs the original videoHandle, videoGenEntId, and structuredOutput from the source.
Vibes uses a single cookie, meta_session, for authentication. The cookie value is a UUID session token.
-
Log in at vibes.ai in your browser (currently requires a Meta/Facebook account).
-
Open DevTools (F12) β Application β Cookies β
https://vibes.ai. -
Copy the value of
meta_session(a long string with a UUID format likee60e910a-...-K54E). -
Pass it to the client:
client = VibesClient(meta_session="e60e910a-...")
Or via env var:
export VIBES_META_SESSION="e60e910a-..."
Cookies expire. The web app refreshes them silently via /api/auth/me. When you start getting 401 Unauthorized errors, grab a fresh cookie from the browser and create a new VibesClient. You said you'll rotate them β this is the only manual step.
The TTS endpoint (/api/studio/playai/tts) depends on a server-side Facebook access token that rotates independently of your meta_session. If you see 403 Facebook expired access token, just wait a few minutes and retry. The Vibes backend auto-refreshes this token on its own schedule.
All endpoints are under https://vibes.ai/api/. This list was extracted directly from the Next.js JS bundles.
GET /api/auth/meβ current userPOST /api/auth/logoutβ invalidate sessionPOST /api/auth/check-tokenβ token validationGET /api/system-statusβ system status bannerPOST /api/analyticsβ usage analytics (fire-and-forget)POST /api/bug-reportβ bug reportingPOST /api/consent/recordβ cookie consentGET /api/quota/upsellβ upsell info
GET /api/projectsβ list (params:limit,offset,sort,search)POST /api/projectsβ createGET /api/projects/{id}β getPUT /api/projects/{id}β update name/compositionDELETE /api/projects/{id}?deleteAssets=trueβ deletePOST /api/projects/{id}/duplicateβ duplicatePOST /api/projects/{id}/uploadβ bulk upload mediaGET /api/projects/{id}/batches?limit=6&offset=0β list batches in projectGET /api/projects/{id}/assetsβ list project assetsPOST /api/projects/{id}/assetsβ add assetPOST /api/projects/{id}/assets/importβ import from another projectGET /api/projects/{id}/assets/available?sourceProjectId={id}β list importablePOST /api/projects/{id}/timeline/downloadβ sync export to MP4POST /api/projects/{id}/timeline/export-surfguardβ start async exportGET /api/projects/{id}/timeline/export/{exportId}/statusβ poll exportPOST /api/projects/{id}/timeline/export/{exportId}/cancelβ cancel
GET /api/generation-batches?limit=12&offset=0β list (optionalprojectId,type)POST /api/generation-batchesβ create (body must include client-generated UUID v7 asid)GET /api/generation-batches/{id}β get full statePUT /api/generation-batches/{id}β updateDELETE /api/generation-batches/{id}β deleteGET /api/generation-batches/{id}/streamβ SSE stream of batch updates
POST /api/generate/videosβ text-to-video, image-to-video, extend, v2v edit, image animate (all via differenttypeandconfigvalues)POST /api/generate/imagesβ text-to-image (synchronous)POST /api/generate/image-editβ edit an existing imagePOST /api/generate/promptsβ prompt enhancement (returns 4 variations)POST /api/animate/generateβ lip sync / animation
GET /api/studio/ingredients?ownerFilter=LIBRARY|VIEWER&ingredientType=...β list ingredientsPOST /api/studio/ingredientsβ create ingredientDELETE /api/studio/ingredients/{id}β delete ingredientGET /api/studio/voicesβ list TTS voicesPOST /api/studio/playai/ttsβ text-to-speech (body:{text, voice, outputFormat, language?})
POST /api/upload-imageβ base64 image upload (body:{image: "<base64>"})POST /api/upload-mediaβ multipart form (file+filename)POST /api/upload-video-directβ multipart form (video)POST /api/upload-audio-directβ multipart form (audio)POST /api/upload-profile-pictureβ profile picture
GET /api/media-library?limit=50&offset=0&type=&sort=&search=β listGET /api/download/video?id={contentItemId}β download video MP4GET /api/download/png?id={contentItemId}β download image PNGGET /api/download/{type}?id={id}β generic downloadPOST /api/content-items/{id}/favoriteβ toggle favoritePOST /api/content-items/{id}/retryβ retry failed itemPOST /api/content-items/{id}/feedbackβ submit feedbackDELETE /api/content-items/{id}β delete onePOST /api/content-items/bulk-deleteβ bulk delete (body:{ids: [...]})
GET /api/meta-music?q=&limit=&cursor=β search Meta music libraryGET /api/meta-music/lookup?id=&title=β resolve track thumbnailPOST /api/meta-music/oa-checkβ check original audio statusPOST /api/media/music/clipβ clip a music track segmentPOST /api/media/audio/clipβ clip any audio URLGET /api/proxy-audioβ proxy audio through Vibes CDNGET /api/resolve-audio-urlsβ resolve audio CDN URLs
GET /api/moodboardsβ listPOST /api/moodboardsβ createGET /api/moodboards/{id}β getDELETE /api/moodboards/{id}β deleteGET /api/playablesβ list playables (currently disabled:"Playables not enabled")
POST /api/timeline/chat/streamβ streaming SSE chat (body:{input, instructions, tools?, composition?})- Event types:
message_delta,message_done,tool_call,tool_response,reasoning_delta,reasoning_done,completed,error - Default tools (sent by the client):
generate_image,generate_video,add_music,add_text_overlay,update_text_overlay,resize_clip,move_clip,extend_timeline_to,delete_clip,delete_track,split_clip,duplicate_clip,set_fade,set_volume,set_speed,mute_track,rename_track,reorder_clips,generate_lipsync,create_ingredient_from_clip
- Event types:
POST /api/share-linksβ create (body:{entityType, entityId, expiresAt?, maxUses?})GET /api/share-links?entityType=&entityId=β listDELETE /api/share-links/{id}β revokeGET /api/collaborators?entityType=&entityId=β listDELETE /api/collaborators/{id}β remove
GET /api/sync?entityType=&entityId=β get last-updated timestampGET /api/sync/stream?entityType=&entityId=β SSE stream of update events (snapshot,update,bye)
POST /api/settings/delete-accountPOST /api/settings/delete-all-mediaPOST /api/settings/remove-all-posts
POST /api/meta-graphqlβ Meta GraphQL proxy (body:{doc_id, variables})POST /api/meta-oidc/startβ start OIDC flowPOST /api/meta-profiles/publishβ publish profilePOST /api/revisionsβ session revisions
Ten ready-to-run example scripts in examples/:
01_generate_video.pyβ end-to-end video generation02_images_and_edits.pyβ image generation + editing + media library03_tts_and_lipsync.pyβ TTS β upload β lip sync pipeline04_prompts_and_chat.pyβ prompt enhancement + timeline AI chat05_ingredients.pyβ using saved characters in generations06_extend_video.pyβ π auto-extend and manual-extend a video07_ingredients_full.pyβ π character + style + scene combos08_create_ingredient.pyβ π create a new ingredient via API09_start_end_frame.pyβ π image-to-video with keyframe interpolation10_edit_video.pyβ π video-to-video editing (re-render with directive)
Run any of them with:
export VIBES_META_SESSION="..."
python /home/z/my-project/download/vibes-api/examples/01_generate_video.py- Cookie rotation β
meta_sessionexpires. Re-grab from the browser when 401s appear. - TTS backend token β
/api/studio/playai/ttsdepends on a server-side FB token that rotates independently. If you get403 Facebook expired access token, wait and retry. - Generation quotas β Vibes enforces per-user quotas (visible in the UI). Hit it and you'll get
429or aGENERATION_FAILEDwith quota detail. - No public API β All endpoints here are private and could change at any time. Pin to a client version if stability matters.
- Content IDs for download β
download_video(id)expects the formatbatch-{uuid}-content-{n}. The client uses thebatch-prefix consistently so this works for client-generated batches. - Rate limiting β Don't hammer the API. The client uses a single
requests.Session; if you need parallelism, instantiate multiple clients and rotate cookies. - Aspect ratios β Only
1:1,9:16,16:9are supported (server-enforced). Other values returnGENERATION_FAILED. - Video extend requires full content item β
extend_video(source_video=...)needs the full content item dict (fromget_batch()), not just an ID. The client extractsvideoHandle,videoGenEntId, andstructuredOutputfrom it. - v2v edit may fail on old videos β
edit_video()requiresvideoHandlemetadata which older videos may not have. You'll get a clear error message in that case. - Sentry analytics β The web app posts to Sentry for error tracking. This client does not replicate that (it's noise for API use).
# Install in editable mode
pip install VibesAI-api
# Run tests (requires VIBES_META_SESSION env var)
pytest
# Build CLI
python -m vibes_api.cli --helpvibes-api/
βββ pyproject.toml
βββ README.md
βββ QUICKREF.md
βββ TEST_RESULTS.md
βββ vibes_api/
β βββ __init__.py # Public API surface
β βββ client.py # VibesClient main implementation (~2400 lines, 87 methods)
β βββ cli.py # Argparse-based CLI
β βββ models.py # Enums: AspectRatio, Resolution, VideoModel, etc.
β βββ ingredients.py # Ingredient payload builders
βββ examples/
β βββ 01_generate_video.py
β βββ 02_images_and_edits.py
β βββ 03_tts_and_lipsync.py
β βββ 04_prompts_and_chat.py
β βββ 05_ingredients.py
β βββ 06_extend_video.py # π
β βββ 07_ingredients_full.py # π
β βββ 08_create_ingredient.py # π
β βββ 09_start_end_frame.py # π
β βββ 10_edit_video.py # π
βββ research/
βββ ... (reversing notes, sample responses, screenshots)
MIT. This project is not affiliated with Meta or Vibes. Use at your own risk; respect Vibes' Terms of Service.