Transloadit's Assembly system is genuinely useful for complex file processing pipelines: encode a video, generate a thumbnail, apply a watermark, store to S3, fire a webhook — all defined in one JSON object. If your application does any combination of those things, Transloadit is well-suited.
But many teams have Assemblies that do exactly one thing: convert a file from format A to format B. They're using the Assembly model for simplicity — to avoid running FFmpeg or LibreOffice themselves — not because they need multi-step chaining. For those teams, Transloadit's pricing and Assembly overhead can be replaced by a simpler, cheaper API call.
When migrating from Transloadit makes sense
Your Assemblies do only one conversion step. If you have an Assembly that converts mp4 to webm, or docx to pdf, using Transloadit just to avoid running FFmpeg yourself — ChangeThisFile does the same thing with no Assembly setup and lower cost.
You don't use Uppy. Transloadit's main frontend differentiator is Uppy, an open-source upload widget with Transloadit integration. If you handle file uploads yourself (drag-and-drop, file picker, or backend-to-backend), you're not using Transloadit's signature frontend feature.
You don't need S3/cloud storage output. Transloadit can write processed files directly to S3, GCS, or FTP. If you download the result and store it yourself, you're not using that feature either.
Credit system limits are hitting you. Transloadit's credit system assigns different credit costs to different robots. Complex encoding robots cost more credits than simple conversions. ChangeThisFile charges one unit per conversion regardless of format type.
Who should stay on Transloadit:
- Multi-step Assemblies (encode + thumbnail + watermark in one job)
- Uppy upload widget in your frontend
- Direct S3/GCS output from processing
- Webhook on Assembly completion
- Video thumbnail extraction with frame selection
- Watermarking images or video
Cost comparison
| Volume/month | Transloadit (est.) | ChangeThisFile | Monthly savings |
|---|---|---|---|
| 500 conversions | ~$39/mo (entry plan) | $0 (free tier) | $39 |
| 2,000 conversions | ~$39–79/mo | $29 (Hobby) | $10–50 |
| 10,000 conversions | ~$99–199/mo | $29–99 (Hobby/Startup) | $0–170 |
| 50,000 conversions | ~$299–499/mo | $99–499 (Startup/Scale) | $0–400 |
Transloadit's credit system means actual cost depends on your mix of robots. Video encoding costs more credits than document conversion. Estimates above assume a mixed workload. Video-heavy pipelines are at the higher end.
API approach comparison
| Transloadit concept | ChangeThisFile equivalent |
|---|---|
| Assembly definition (JSON) | Single POST /v1/convert |
| Robot (e.g., /video/encode, /document/convert) | target field ("mp4", "pdf", etc.) |
| Assembly Steps[] array | Not needed — one call, one output |
| Auth header + signature (HMAC) | Authorization: Bearer ctf_sk_{key} |
| Async Assembly + notification_url webhook | Synchronous — file in response |
| GET Assembly result URL (download) | Not needed — file in response body |
| Uppy upload widget | Not included — handle uploads yourself |
| S3/GCS output robot | Not supported — download and store yourself |
Code migration: BEFORE and AFTER
# BEFORE: Transloadit (Assembly, HMAC auth, async + polling)
import requests
import hmac
import hashlib
import json
import time
TL_AUTH_KEY = 'your_transloadit_auth_key'
TL_SECRET = 'your_transloadit_secret'
# Build Assembly params
params = json.dumps({
'auth': {
'key': TL_AUTH_KEY,
'expires': '2026-12-31T23:59:59.000Z'
},
'steps': {
'convert': {
':use': ':original',
'robot': '/document/convert',
'format': 'pdf',
'result': True
}
}
})
# HMAC signature
signature = hmac.new(
TL_SECRET.encode('utf-8'),
params.encode('utf-8'),
hashlib.sha384
).hexdigest()
# Submit Assembly with file
with open('report.docx', 'rb') as f:
resp = requests.post(
'https://api2.transloadit.com/assemblies',
data={'params': params, 'signature': f'sha384:{signature}'},
files={'file_input': f}
)
assembly_id = resp.json()['assembly_id']
# Poll for completion
while True:
status = requests.get(
f'https://api2.transloadit.com/assemblies/{assembly_id}',
params={'auth_key': TL_AUTH_KEY}
).json()
if status['ok'] == 'ASSEMBLY_COMPLETED':
download_url = status['results']['convert'][0]['url']
break
if status['ok'] == 'ASSEMBLY_UPLOADING_ERRORED':
raise Exception('Assembly failed')
time.sleep(2)
# Download result
result = requests.get(download_url)
with open('report.pdf', 'wb') as f:
f.write(result.content)
# AFTER: ChangeThisFile (static Bearer token, synchronous)
import requests
response = requests.post(
'https://changethisfile.com/v1/convert',
headers={'Authorization': 'Bearer ctf_sk_your_key'},
files={'file': open('report.docx', 'rb')},
data={'target': 'pdf'}
)
with open('report.pdf', 'wb') as f:
f.write(response.content)
Key differences: HMAC signature generation is replaced by a static Bearer token; the Assembly JSON definition is replaced by a single target field; the polling loop and download URL step are eliminated.
Auth migration: HMAC to Bearer token
Transloadit uses HMAC-SHA384 request signing — your auth key + secret are used to sign each request's params JSON. This is secure but requires signing logic in every language you use. ChangeThisFile uses a static Bearer token in the Authorization header.
- Get your CTF key: changethisfile.com/v1/keys/free. Free, no card. Format:
ctf_sk_.... - Remove HMAC signing logic: Delete the
hmac.new()/hashlib.sha384code and the expiry timestamp generation. Replace the entire auth block withheaders={'Authorization': f'Bearer {CTF_KEY}'}. - Remove Assembly definition code: Delete the
stepsJSON, robot configuration, and params object. The target format is now a simple multipart field:data={'target': 'pdf'}. - Update environment variables: Replace
TRANSLOADIT_AUTH_KEYandTRANSLOADIT_SECRETwith a singleCTF_API_KEY.
Webhook migration
Transloadit fires a notification_url webhook when an Assembly completes. ChangeThisFile is synchronous — the converted file is in the HTTP response, so there's no need for a webhook.
If you used Transloadit webhooks for completion notification: Remove the webhook handler. The code that ran inside it should run after the response = requests.post(...) call returns.
If you used Transloadit webhooks for error handling: Use a try/except block around the ChangeThisFile call. response.raise_for_status() throws on 4xx/5xx. Add retry logic if needed:
try:
response = requests.post(
'https://changethisfile.com/v1/convert',
headers={'Authorization': f'Bearer {CTF_KEY}'},
files={'file': open('doc.docx', 'rb')},
data={'target': 'pdf'},
timeout=120
)
response.raise_for_status()
except requests.HTTPError as e:
# Handle error — no webhook needed
print(f'Conversion failed: {e.response.status_code}')
Rollback plan
Keep your Transloadit account active during the migration period:
- Abstract conversion calls behind a function with a backend parameter. Toggle
CONVERTER_BACKEND=transloaditorCONVERTER_BACKEND=ctfto switch instantly. - If your Assembly uses multiple steps (e.g., convert + thumbnail), identify which steps can move to ChangeThisFile individually and which must stay as a pipeline.
- Run parallel for 48–72 hours comparing outputs before switching all traffic.
- Cancel your Transloadit plan after 30 days of clean operation.
Common migration questions
My Assembly uses multiple steps — can I migrate partially?
Yes. Migrate the simple single-step Assemblies to ChangeThisFile and keep complex multi-step ones on Transloadit. You'll reduce your Transloadit credit usage (and cost) while keeping the features that need the pipeline model.
I use Uppy for file uploads. Does ChangeThisFile integrate with it?
ChangeThisFile doesn't have an Uppy plugin. If Uppy sends files to Transloadit, that integration stays on Transloadit. If you can decouple the upload from the conversion, handle uploads with a standard file picker and send completed uploads to ChangeThisFile's API.
Transloadit supports 100+ robots. Does ChangeThisFile cover all of them?
No. Transloadit has robots for watermarking, thumbnail generation, audio normalization, video clip extraction, CDN store, and more. ChangeThisFile covers format conversion only. Audit which robots you actually use — many teams use 1–2 robots despite having access to 100+.
What's the file size limit for ChangeThisFile?
Free tier: 25MB. Paid plans support larger files. Transloadit handles larger files and long-running encoding jobs better than ChangeThisFile's synchronous model for large video files.
Transloadit is the right tool for multi-step processing pipelines. ChangeThisFile is the right tool when your Assembly does exactly one thing — convert a file's format. Identify your single-step Assemblies, get a free API key, and migrate those first. Keep the rest on Transloadit.