skills-il/developer-tools/cloudinary-assets
Claude Code and agent skill by skills-il/developer-tools
- community
Checking that the SKILL.md file is still in the repository.
Manage media assets through Cloudinary's REST API -- upload, transform, optimize, and deliver images and videos. Use when user asks about image upload, media optimization, image transformations, responsive images, video management, CDN delivery, or mentions Cloudinary specifically. Covers Upload API, Admin API, URL-based transformations, AI-powered effects (gen_remove, gen_replace, background removal), and delivery optimization. Israeli-founded (2012) with R&D in Petah Tikva; global HQ in San Jose, California. Do NOT use for non-Cloudinary media hosting or local image processing without cloud upload.
Install
npx vskill@latest install skills-il/developer-tools/cloudinary-assetsSKILL.md
Cloudinary Assets
Instructions
Step 1: Verify Cloudinary Configuration
Check for Cloudinary credentials:
If not configured, guide the user:
- Sign up at https://cloudinary.com (free tier: 25 credits per month)
- Find the cloud name, API key and secret on the API Keys page of the Console Settings
- Set CLOUDINARY_URL=cloudinary://API_KEY:API_SECRET@CLOUD_NAME
Step 2: Choose Operation
| Operation | API | Method | When | |
|---|---|---|---|---|
| Upload image | Upload API | POST /image/upload | New image to store | |
| Upload video | Upload API | POST /video/upload | New video to store | |
| Transform image | URL-based | GET (URL) | Resize, crop, effects | |
| Optimize delivery | URL-based | GET (URL) | Performance improvement | |
| List assets | Admin API | GET /resources | Browse media library | |
| Delete asset | Upload API | POST /{resource_type}/destroy | Remove media (image, video or raw) | |
| Get asset details | Admin API | GET /resources/{id} | Check metadata |
Step 3: Upload Media
Upload an image:
Files over 100 MB (most real videos) cannot go through this single POST. Cloudinary requires chunked upload for them: use the server SDK's upload_large (cloudinary.uploader.upload_large in Python, cloudinary.v2.uploader.upload_large in Node) and ALWAYS pass resource_type="video" for a video. Do not rely on the SDK default: in the current SDK source upload_large falls back to raw, and a raw asset gets no video transformations, so every /video/upload/ URL for it fails. Chunking does not lift your plan's size cap (see Troubleshooting). For video eager transformations also pass eager_async=true so encoding runs in the background instead of blocking the upload, and eager_notification_url to be told when it finishes.
Uploads from a browser or Next.js app. Never ship api_secret to the client. There are two documented routes, and either one is also the fix for a "blocked by CORS policy" error on a direct browser upload:
- Signed (preferred for user uploads). The browser asks your server for a signature, then uploads
directly. With next-cloudinary, give CldUploadWidget a signatureEndpoint: ``ts // app/api/sign-cloudinary-params/route.ts (server only) import { v2 as cloudinary } from "cloudinary"; export async function POST(request: Request) { // Authenticate the caller first: this route signs whatever it is sent. const { paramsToSign } = await request.json(); const signature = cloudinary.utils.api_sign_request(paramsToSign, process.env.CLOUDINARY_API_SECRET!); return Response.json({ signature }); } ` `tsx import { CldUploadWidget } from "next-cloudinary"; <CldUploadWidget signatureEndpoint="/api/sign-cloudinary-params"> {({ open }) => <button onClick={() => open()}>Upload</button>} </CldUploadWidget> ` Env: NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME, NEXT_PUBLIC_CLOUDINARY_API_KEY (the key may be public), CLOUDINARY_API_SECRET (server only). next-cloudinary also ships CldImage and CldVideoPlayer` for delivery.
- Unsigned. An unsigned
upload_presetnamed in the request. Anyone who sees the preset name can
upload with it, so harden it (see Gotchas).
Step 4: Transform Images via URL
Build transformation URLs using this pattern:
Common transformation recipes:
| Goal | Transformation | Example | |
|---|---|---|---|
| Thumbnail | w_150,h_150,c_fill,g_face | Face-aware 150x150 thumbnail | |
| Hero image | w_1200,h_600,c_fill,q_auto,f_auto | Optimized hero banner | |
| Profile avatar | w_200,h_200,c_thumb,g_face,r_max | Circular face crop | |
| Product image | w_800,h_800,c_pad,b_white | Padded on white background | |
| Social share | w_1200,h_630,c_fill | OpenGraph image size | |
| Watermarked | l_{your_logo_public_id},w_200,o_50/fl_layer_apply,g_south_east | Semi-transparent watermark. Replace the placeholder with a real public ID: l_watermark on an account without that asset returns 400 Resource not found - watermark |
Folder mode matters. Cloudinary has two modes and new product environments are created in dynamic folder mode. In dynamic folder mode the parameter that places an asset in the folder tree is asset_folder, and it does NOT affect the public ID. The older folder parameter is the fixed-folder-mode parameter, where the folder becomes part of the public ID. Passing folder on a dynamic-folder account therefore does not do what a fixed-folder tutorial implies. Check your product environment's folder mode in Settings before scripting bulk uploads, and pass asset_folder when you are in dynamic mode.
Step 4b: AI-Powered Transformations
Cloudinary's generative AI effects (gen_remove, gen_replace, gen_background_replace, gen_recolor, gen_restore) are available as e_gen_* URL params. Generative fill is the exception: it is a background qualifier b_gen_fill:prompt_<text> used with a padding crop in the SAME component, e.g. c_pad,w_1600,h_900,b_gen_fill:prompt_beach (200). Two traps: the prompt is unparenthesized like e_gen_background_replace (b_gen_fill:prompt_(beach) returns HTTP 500 General Error), and without a padding crop it returns HTTP 400 gen_fill only available for padding crop modes that fills a padded area, NOT an e_gen_fill effect (constructing e_gen_fill:... returns a 400). Some variants may still be flagged as Beta on the docs page, so check the current status before relying on a specific effect in production:
| Param | What it does | |
|---|---|---|
e_gen_remove:prompt_(person) | AI removes the matched object from the image | |
e_gen_replace:from_car;to_bicycle | AI replaces one object with another (documented form is unparenthesized). A 400 Invalid input for gen_replace usually means the from object was not found in the image, not that the syntax is wrong | |
e_gen_background_replace:prompt_beach%20at%20sunset | Generative background swap. Note the prompt is NOT parenthesized for this effect: prompt_(beach) returns HTTP 500 General Error, while prompt_beach returns 200. The parenthesized form is correct for e_gen_remove but not here | |
e_background_removal | Background removal, a built-in transformation (no separate add-on subscription; the legacy add-on is closed to new accounts from Feb 1 2026). It is NOT free, it bills via special transformation counting. | |
e_gen_restore | AI restoration for old, blurry, or damaged photos | |
auto_tagging:0.7 | Auto-tag uploads via AI (confidence threshold 0.0-1.0); pass at upload time. Unlike the e_gen_* effects this is NOT built in: it requires registering a tagging add-on (Google Auto Tagging, AWS Rekognition, Imagga) on the Add-ons page first, otherwise the upload returns an error instead of tags |
Example: remove a person from the background, then replace background:
Auto-tagging at upload time:
Step 5: Optimize for Performance
Apply automatic optimization:
Generate responsive breakpoints:
HTML responsive image tag:
Video delivery. Deliver from /video/upload/, not /image/upload/ (the same public ID under the image path is a different asset, usually a 404):
| Goal | URL | |
|---|---|---|
| Optimized progressive MP4/WebM | .../video/upload/q_auto,f_auto:video/{public_id} (use f_auto:video when the URL has no extension: with plain f_auto, a request whose Accept header lists image types, as a browser navigation does, gets an AVIF image instead of the video) | |
| Adaptive bitrate streaming (HLS) | .../video/upload/sp_auto/{public_id}.m3u8 (.mpd for DASH). Play it with an HLS/DASH-capable player such as the Cloudinary Video Player | |
| Poster frame | .../video/upload/so_5,w_800,h_450,c_fill,q_auto,f_jpg/{public_id} |
q_auto on an .m3u8 is NOT adaptive streaming: it returns a single-rendition playlist. Only sp_auto (or a named streaming profile) produces the multi-rendition master playlist. Restrict an image URL to image candidates with f_auto:image.
Step 6: Manage Assets
List all assets:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingcloudinary-assets/SKILL.md
Popularity
- Repository stars
- 1
- Repository forks
- 1
- 7-day trend score
- 3
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 20 Mar 2026, 7 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/skills-il/developer-tools/cloudinary-assets)