GLB to USDZ Converter - AR Quick Look Ready (API) avatar

GLB to USDZ Converter - AR Quick Look Ready (API)

Pricing

from $90.00 / 1,000 conversion successes

Go to Apify Store
GLB to USDZ Converter - AR Quick Look Ready (API)

GLB to USDZ Converter - AR Quick Look Ready (API)

Convert GLB/glTF to USDZ via API - no Mac, no Xcode. Every file is validated against Apple's ARKit rules and shipped with a QC report: correct PBR materials, Draco/KTX2 support, batch mode, previews, n8n & MCP ready. Fair billing: no valid file, no conversion charge.

Pricing

from $90.00 / 1,000 conversion successes

Rating

5.0

(1)

Developer

Sergey Faraday

Sergey Faraday

Maintained by Community

Actor stats

2

Bookmarked

1

Total users

0

Monthly active users

12 days ago

Last modified

Share

GLB to USDZ Converter - AR Quick Look Ready

Convert GLB and glTF to USDZ that opens correctly in Apple AR Quick Look - via API, no Mac required. Every file is ARKit-validated and returned with a machine-readable QC report, so what you ship to iPhone, iPad, and visionOS is checked before you pay for it.

Apple has retired its usdzconvert / USDPython tools, and the free browser converters run client-side with no API - a pipeline, a CI job, or an AI agent can't click a browser button. This Actor is the server-side path: URL in, validated .usdz and report out.

Quick start

curl -X POST "https://api.apify.com/v2/acts/YOUR_USERNAME~glb-to-usdz/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"source": ["https://example.com/model.glb"]}'

For files that may take over a minute, use the async flow instead - see n8n integration below.

Convert GLB to USDZ in Python - the usdzconvert replacement

Apple's usdzconvert / USDPython toolchain is discontinued, and it only ever ran on macOS. To convert GLB to USDZ in Python now, on any OS, call the Actor with the official client:

from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("YOUR_USERNAME/glb-to-usdz").call(
run_input={"source": ["https://example.com/model.glb"], "textureMaxSize": 2048},
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["status"], item["arkitCompatible"], item["usdzUrl"])

No Blender scripting, no OpenUSD compilation, no usd_from_gltf build headaches - the USD toolchain runs inside the Actor.

No Mac? No Xcode? No problem

Reality Converter is a macOS GUI app. usdzconvert required a Mac and is now retired. This Actor converts GLB to USDZ on Windows, Linux, CI runners, and serverless pipelines - anywhere you can make an HTTP request. If you've been keeping a Mac mini alive just to produce USDZ files for iOS AR, you can retire it.

Sample report

Each input file produces one dataset row:

{
"schemaVersion": "1.0",
"converterVersion": "1.2.0",
"source": "https://example.com/model.glb",
"fileIndex": 0,
"status": "ok_with_warnings",
"arkitCompatible": true,
"usdzUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/usdz-abc123.usdz",
"previewUrl": null,
"validation": {
"gate": "ARKit ComplianceChecker",
"gateVersion": "25.11",
"errors": 0,
"warnings": 0
},
"issues": [],
"warnings": [
{ "code": "MORPH_STRIPPED", "message": "Morph targets are not supported and were removed." }
],
"stats": {
"inputSizeMB": 4.2,
"outputSizeMB": 3.8,
"triangles": 12400,
"meshes": 3,
"materials": 2,
"textures": [
{ "name": "albedo", "from": "png 4096x4096", "to": "jpeg 2048x2048", "width": 2048, "height": 2048, "files": 1 }
],
"animations": { "kept": 1, "stripped": 0, "resampled": 1, "skelStripped": 0 },
"unitScaleApplied": 1
},
"timings": {
"fetchSec": 0.8,
"preprocessSec": 1.2,
"convertSec": 3.4,
"uploadSec": 0.3,
"totalSec": 5.7
},
"idempotencyKey": "sha256:abc123..."
}

status is ok only when the row carries no warnings at all; any warning - even a harmless stripped morph target - makes it ok_with_warnings, and a missing deliverable makes it failed.

Validate an existing USDZ file

Already have a .usdz that "doesn't work in AR"? Run it through the same ARKit compliance checker without converting anything - $0.03 per file:

curl -X POST "https://api.apify.com/v2/acts/YOUR_USERNAME~glb-to-usdz/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"mode": "validateOnly", "source": ["https://example.com/model.usdz"]}'

The row comes back with arkitCompatible, the gate's error/warning counts, and every finding as a coded issue. Works for USDZ files produced by any tool, and for .usdz records in your own key-value store (uploadStore + uploadRecords; API names sourceKeyValueStore / sourceKeys still accepted).

Does it keep animations?

Honest answer, because most converters break here:

  • Transform animations (translation / rotation / scale clips) - preserved, resampled to LINEAR at 30 fps and exported as USD time samples. Product turntables, hovering objects, opening lids survive.
  • Skeletal (rigged) animation - the mesh is converted at a clean bind pose with an explicit SKEL_STRIPPED warning. UsdSkel authoring is on the roadmap; we don't silently ship broken rigs.
  • Morph targets / blend shapes - not supported by AR Quick Look; stripped with a MORPH_STRIPPED warning, never silently.

Every degradation is a named warning code in the report. You always know what changed.

glTF to USDZ - including multi-file scenes

Multi-file glTF scenes (.gltf + external .bin + textures) are supported: submit them as a zip, or as a .gltf URL whose relative resources resolve automatically. Binary .glb works as-is. Draco- and meshopt-compressed meshes are decoded; KTX2/Basis and WebP textures are transcoded to USDZ-compatible PNG/JPEG with size limits you control.

ARKit validation - because "converted" is not "working"

A .usdz that opens on your desktop can still fail on an iPhone. Every output here runs through Apple's ARKit compliance checker (from OpenUSD) before you're charged for it:

  • arkitCompatible: true/false on every file, from the real checker - not a guess
  • failOn: error | warning | never - you choose whether non-compliant files are delivered
  • mode: reportOnly - validate the whole conversion pipeline for $0.03 without buying the file

Why your USDZ looks wrong in AR Quick Look

USDZ model appears black or plastic

Metallic-roughness channels must be split into separate grayscale inputs for UsdPreviewSurface; naive converters wire the packed ORM texture straight in and get shiny black plastic. This Actor splits the channels, sets the color space per texture (sRGB for color, raw for data), and folds normalScale / occlusionStrength into the texture network instead of dropping them.

Model is 100× too big (or too small) in AR

glTF is meters; many DCC exports aren't. Rather than silently rescaling your geometry, the report tells you the applied factor and warns on a suspicious scene size (SUSPICIOUS_SCALE). Fix it in one option: targetHeight: 1.5 ("make it 1.5 m tall"), or sourceUnits: "cm" if you know what the DCC exported.

GLB with animation breaks in USDZ

Transform clips are kept; skeletal rigs and morph targets are the parts Quick Look can't play, and they are removed with named warnings instead of producing a frozen or exploded mesh. Set animation: strip if you want a static asset on purpose.

Symptom → cause → where to look

SymptomWhat happenedWhat to check
Model invisible or blackMissing or incompatible materialsissues[] for material codes
Wrong scale (tiny/huge)Unit mismatchstats.unitScaleApplied, try sourceUnits (e.g. "cm") or targetHeight
No texturesSource uses KTX2/WebP without extensionswarnings[] for texture codes
Transparency brokenAlpha mode incompatibilityTry alphaHandling: forceOpaque
Missing animationNon-transform animation strippedwarnings[] for SKEL_STRIPPED
Morph targets goneNot supported by USDZ/ARKitwarnings[] for MORPH_STRIPPED
Dark/flat appearanceUnlit material approximatedwarnings[] for UNLIT_APPROXIMATED
Sheen/transmission approximatedMapped onto opacity/roughness (no refraction)warnings[] for TRANSMISSION_APPROXIMATED / SHEEN_APPROXIMATED
Specular strength approximatedFolded into ior (tint averaged)warnings[] for SPECULAR_APPROXIMATED
Anisotropy/iridescence lostNo UsdPreviewSurface equivalentwarnings[] for ANISOTROPY_DROPPED / IRIDESCENCE_DROPPED
Wrong orientation / tilingCoordinate system or texture transformstats.textures; KHR_texture_transform is authored as UsdTransform2d with the UV flip
File won't open in Quick Look at allPackage layoutPackaged through the official USD API (uncompressed, aligned) - check issues[] for gate errors
Gate errors on valid modelStrict compliance checkSet failOn: never to deliver anyway
File too largeInput exceeds 250 MB limitSplit model or reduce textures
SSRF blockedPrivate/loopback URL rejectedUse a public URL or KVS input

Fair billing

A failed conversion never bills conversion-success. Early failures (bad URL, not a GLB, SSRF blocked, too large, empty scene) bill nothing - $0. Actor start is free.

PathPriceWhen
Conversion success (≤ 50 MB)$0.12USDZ delivered to KV store
Large file surcharge (> 50 MB)+$0.10On top of conversion-success
Preview render+$0.02outputPreview: true and the PNG was actually delivered
Validation report only$0.03reportOnly / validateOnly mode, or failOn-driven USDZ withholding
Dedup hit$0Same file+options already converted in this run
Early failure$0Fetch/sniff/preprocess error, budget exhausted

Every output is validated for AR Quick Look using the ARKit ComplianceChecker from OpenUSD.

Output retention

Output URLs are temporary run artifacts - copy the USDZ to permanent storage. The usdzUrl in each report row points to a key-value store record that expires with the run's default retention period. Your models live only in your run's storage under your account; there is no public gallery and no reuse.

MCP / agent integration

This Actor is exposed under the slug glb-to-usdz via Apify's Actor-MCP bridge - callable as a tool from Claude, Cursor, and any MCP client. When calling it as an MCP tool:

  • For one model, pass a single-item source array
  • Latency is seconds to about a minute per file depending on size and texture count
  • On a status: failed result, surface issues[] to the user - do not blind-retry
  • Check arkitCompatible and warnings[] before presenting the result as successful
  • The usdzUrl is temporary; if the user needs to keep the file, copy it

n8n integration

Use the async chain as the primary recipe - the sync endpoint's ~300 s limit sits at the per-file deadline, so large files on the sync path appear as broken integrations.

  1. Start run - POST /v2/acts/YOUR_USERNAME~glb-to-usdz/runs with input JSON
  2. Poll status - GET /v2/actor-runs/{runId} until status is SUCCEEDED or FAILED
  3. Get results - GET /v2/datasets/{defaultDatasetId}/items
  4. Download USDZ - GET the usdzUrl from each row (no token needed, public URL)

For small files under 1 minute, the synchronous endpoint works: POST /v2/acts/YOUR_USERNAME~glb-to-usdz/run-sync-get-dataset-items

An n8n workflow template is available at templates/n8n/glb-to-usdz.json. The same recipe fits Make, CI (convert and validate 3D assets on every commit), and e-commerce back ends that generate AR Quick Look assets for every uploaded product model.

Input schema

FieldTypeDefaultNotes
uploadedModelsstring[]nullFiles dropped into the console's upload widget (.glb / .gltf / .zip); no API needed. Combines with the inputs below
sourcestring[]nullURL(s) to GLB/glTF/ZIP files. Batch up to 200.
uploadStorestringnullApify KVS to read files from, or the store an upload landed in (grants read access to a limited-permission run); combines with source / uploadedModels. Legacy API name sourceKeyValueStore still accepted
uploadRecordsstring[]nullRecord names inside the granted store; optional when the store is only granting access for uploadedModels. Legacy API name sourceKeys still accepted
modeconvert | reportOnly | validateOnlyconvertreportOnly: full pipeline, report only, no USDZ ($0.03). validateOnly: validate an existing .usdz (URL or KVS record), no conversion ($0.03)
textureMaxSizeinteger 256-40962048Max texture dimension (longest side); 1024 / 2048 / 4096 are the useful stops
textureFormatauto | png | jpegautoColor textures only; data textures always PNG
unitScaleauto | asIs | numberautoMeters-per-unit scale factor
sourceUnitsmm | cm | m | inches | feetnullUnits the model was authored in; resolves to the numeric scale for you. targetHeight takes precedence if both are set (SCALE_OPTION_OVERRIDDEN warning)
targetHeightnumbernullDesired model height (in targetHeightUnit, meters by default); the converter measures the bounding box and computes the scale. Wins over sourceUnits and numeric unitScale (SCALE_OPTION_OVERRIDDEN warning)
targetHeightUnitm | cm | mm | inches | feetmUnit of targetHeight; converted to meters before processing, so 150 cm and 1.5 m are the same job
animationpreserve | strippreserveTransform animations only
alphaHandlingpreserve | forceOpaquepreserveForce opaque discards alpha
failOnerror | warning | nevererrorControls USDZ delivery on gate findings
outputPreviewbooleanfalseRender a flat 800×800 transparent PNG preview alongside the USDZ (+$0.02). A failed render never blocks the USDZ
targetMaxFileSizeMBnumbernullWarn (TARGET_SIZE_EXCEEDED) when the output USDZ exceeds this size; failOn decides delivery
webhookUrlstringnullPOST the batch summary to this URL when the run completes

Getting the size right in AR

Three user-friendly ways to fix a model that shows up tiny or huge in Quick Look, in order of preference:

  1. targetHeight: 1.5 - "make it 1.5 m tall". No unit archaeology needed.
  2. sourceUnits: "cm" - you know the DCC exported centimeters.
  3. unitScale: 0.01 - the raw numeric factor, for scripts that computed it themselves.

Quick Look's AR texture budget: keep textures ≤ 2048×2048 and ≤ 6 total. The report warns with AR_TEXTURE_BUDGET_WARNING when the output exceeds Apple's recommendation.

Quick Look embedding tip

Lighting in AR Quick Look is controlled on the embed side, not inside the USDZ. When linking a USDZ on the web, you can pin the newer image-based lighting for glossier, more accurate materials:

<a rel="ar" href="model.usdz#preferredIblVersion=2">View in AR</a>

FAQ

How do I convert GLB to USDZ without a Mac? Call this Actor from any OS via HTTP (or the Python client above) - the USD toolchain runs server-side. No Reality Converter, no Xcode, no macOS.

Is Apple's usdzconvert still available? No - Apple has retired its Python USDZ tools. This Actor is a maintained server-side replacement with ARKit validation on top.

Does GLB to USDZ conversion keep animations? Transform animations, yes. Skeletal rigs are converted at bind pose with a warning; morph targets aren't supported by AR Quick Look and are stripped with a warning.

What does "ARKit validated" mean? Every file runs through Apple's ARKit compliance checker inside the Actor. The report says arkitCompatible: true only when the checker finds zero errors - that is what makes the file safe for iOS, iPadOS, and visionOS Quick Look.

Can I check a USDZ I already have? Yes - mode: validateOnly runs the same gate on an existing .usdz for $0.03, no conversion.

Are my models stored? Only in your run's Apify storage, under your account's retention settings. There is no public gallery and no reuse of your models.

Current limits and roadmap

Skeletal (UsdSkel) animation authoring, FBX/OBJ/STL inputs, and USDZ→GLB reverse conversion are not in this version - they are tracked publicly on the roadmap. Previews, validation of existing USDZ files, and multi-file glTF input are already here.