403 Forbidden on Transcode
Common causes of 403 Forbidden errors and how to fix bucket permissions
403 Forbidden on Transcode
If you're getting a 403 Forbidden error when creating a transcode job, it's usually a permissions issue with your storage bucket.
Common Cause: Incorrect Bucket URL
The most common mistake is using a placeholder or example bucket name from the documentation:
❌ Common Mistakes
{
"inputs": [
{ "url": "gs://your-bucket/video.mp4" } // ❌ Literal "your-bucket"
]
}
{
"inputs": [
{ "url": "gs://example-bucket/video.mp4" } // ❌ Example bucket
]
}
{
"inputs": [
{ "url": "gs://my-bucket/video.mp4" } // ❌ Doesn't exist
]
}
✅ Correct Format
Use the actual bucket name from your presigned upload URL:
{
"inputs": [
{ "url": "gs://ffmpeg-micro-uploads-prod/1234567890-video.mp4" }
]
}
How to Get the Correct Bucket URL
Option 1: Use the Presigned Upload Flow
When you upload via the presigned URL flow, save the full GCS URL:
// 1. Get presigned URL
const { uploadUrl, filename } = await fetch('/v1/upload/presigned-url', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
filename: 'video.mp4',
contentType: 'video/mp4',
fileSize: 12345678
})
}).then(r => r.json())
// 2. Upload file
await fetch(uploadUrl, {
method: 'PUT',
body: file
})
// 3. Construct GCS URL for transcode
const gcsUrl = `gs://ffmpeg-micro-uploads-prod/${filename}`
// 4. Create transcode job
await fetch('/v1/transcodes', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
inputs: [{ url: gcsUrl }], // ✅ Correct!
outputFormat: 'mp4',
preset: { quality: 'medium' }
})
})
Other 403 Causes
1. Quota Exceeded
Your account may have hit its monthly quota limit. Check your usage at /dashboard/usage.
Solution: Upgrade your plan or wait until the next billing cycle.
2. API Key Revoked
If you've deleted or regenerated your API key, the old key will return 403.
Solution: Get your current API key from /dashboard/api-keys.
3. Account Suspended
In rare cases, accounts may be suspended for violations of the terms of service.
Solution: Contact support at javid@ffmpeg-micro.com.
Quick Debugging Steps
gs://ffmpeg-micro-uploads-prod/... or gs://your-bucket/...?Example: Complete Upload & Transcode Flow
# 1. Get presigned upload URL
UPLOAD_RESPONSE=$(curl -X POST "https://api.ffmpeg-micro.com/v1/upload/presigned-url" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "video.mp4",
"contentType": "video/mp4",
"fileSize": 12345678
}')
UPLOAD_URL=$(echo $UPLOAD_RESPONSE | jq -r '.result.uploadUrl')
FILENAME=$(echo $UPLOAD_RESPONSE | jq -r '.result.filename')
# 2. Upload file
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: video/mp4" \
--data-binary @video.mp4
# 3. Confirm upload
curl -X POST "https://api.ffmpeg-micro.com/v1/upload/confirm" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"filename\": \"$FILENAME\",
\"fileSize\": 12345678
}"
# 4. Create transcode with correct GCS URL
curl -X POST "https://api.ffmpeg-micro.com/v1/transcodes" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"inputs\": [{
\"url\": \"gs://ffmpeg-micro-uploads-prod/$FILENAME\"
}],
\"outputFormat\": \"mp4\",
\"preset\": {
\"quality\": \"medium\"
}
}"
Still Getting 403?
Contact support at javid@ffmpeg-micro.com with:
Related Articles
Learn how to set up authentication and make your first API request
Where to see your usage limits and what happens when you hit quota
What the file size mismatch error means and how to fix it
Can't find what you're looking for?