# Model Check: Game-Ready GLB/glTF 3D Model Validator (`ocean3d/modelcheck`) Actor

Feed it a GLB model URL, get a game-readiness report: real-world scale sanity, pivot placement, triangle and texture budgets, materials, rig and animation summary. Built for sorting AI-generated models (Meshy, Tripo, etc.) into keepers and junk.

- **URL**: https://apify.com/ocean3d/modelcheck.md
- **Developed by:** [Justin Schroeder](https://apify.com/ocean3d) (community)
- **Categories:** AI, Developer tools, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $30.00 / 1,000 model checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Model Check: is this 3D model actually usable in a game?

Feed it a `.glb` file (or a zip of up to 100), get back a
game-readiness report plus rendered turnaround images, in about a
minute, without opening a 3D tool.

AI generators like Meshy, Tripo, and Hunyuan3D made creating 3D
models nearly free. Sorting the output didn't get cheaper: the files
are *valid*, but half of them are secretly unusable: a "wooden
barrel" that imports 38 meters tall, a prop whose pivot floats 3
meters above the mesh, a phone-melting 2 million triangles on a
background object. Spec validators can't catch any of that, because
none of it violates the glTF spec. The only way to know was to
import each model into an engine and eyeball it.

Model Check does the eyeballing for you.

### What you get per model

**A verdict**, one of `game_ready`, `needs_fixes`, or `not_usable`,
backed by named checks:

| Check | Question it answers |
|---|---|
| `spec_valid` | Will engines even import it? (embedded Khronos glTF validator) |
| `scale_sanity` | Is it a plausible real-world size for what it's supposed to be? |
| `pivot` | Is the origin at the base/center, or floating in space? |
| `tri_budget` | Triangle count vs. your target platform's budget |
| `texture_budget` | Texture sizes, count, and estimated VRAM cost |
| `rig` | For characters: is there a skeleton, how many joints, which clips? |

**Full stats**: dimensions in meters, triangle/vertex/mesh counts,
materials, texture inventory, animation clip list.

**Renders**: a 4-angle turnaround contact sheet and a hero shot, so
you can *see* every model in a batch without importing anything.

Judged against a target you pick: mobile prop, PC prop, character,
hero asset, or report-only (stats without verdicts).

### Example: batch summary

```json
{
  "total": 24,
  "game_ready": 14,
  "needs_fixes": 6,
  "not_usable": 4,
  "models": [
    { "name": "barrel_03.glb", "verdict": "not_usable",
      "failed": ["scale_sanity", "tri_budget"] },
    ...
  ]
}
````

And per model:

```json
{
  "verdict": "needs_fixes",
  "checks": [
    { "id": "pivot", "level": "warn",
      "detail": "Pivot floating: mesh floats 2.70 m above the origin. Placing this in a scene needs manual offset." }
  ],
  "stats": {
    "triangles": 6204,
    "dimensionsMeters": { "x": 0.92, "y": 1.14, "z": 0.88 },
    "textures": [{ "name": "albedo", "size": "1024x1024" }]
  },
  "renders": { "turnaround": "https://...png", "hero": "https://...png" }
}
```

### Who this is for

- **Anyone generating models with AI**: check a whole export folder
  in one run, keep the `game_ready` list, regenerate the rest.
- **Developers buying marketplace assets**: verify scale, budgets,
  and pivots before dropping files into your project.
- **Pipelines and agents**: call it as an API step or an MCP tool
  and gate imports on the verdict (see below).

Engine-agnostic on purpose: glTF is the interchange format used by
Unity, Unreal, Godot, Blender, and the web. A "38 meters tall,
2M triangles" verdict is true everywhere.

### Use it from code

```js
const run = await client.actor("ocean3d/modelcheck").call({
  modelUrl: "https://example.com/my_models.zip",
  targetPreset: "pc_prop"
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const keepers = items.filter(m => m.verdict === "game_ready");
```

### Use it from an AI agent (MCP)

Model Check is callable as an MCP tool through
[Apify's MCP server](https://mcp.apify.com). Point your assistant
(Claude, Cursor, or any MCP client) at it and ask things like
*"generate 20 barrel variations and keep only the game-ready ones"*.
The agent calls Model Check on each candidate and filters by verdict.

### Presets

| Preset | Max tris | Max texture | Expected height |
|---|---|---|---|
| `mobile_prop` | 5,000 | 1024px | 0.05–8 m |
| `pc_prop` | 20,000 | 2048px | 0.05–15 m |
| `character` | 60,000 | 4096px | 1.2–2.6 m |
| `hero_asset` | 150,000 | 4096px | 0.05–30 m |
| `report_only` | n/a | n/a | n/a |

Budgets are deliberately opinionated defaults, tuned from shipping
game props, not spec maximums. `report_only` gives you raw stats if
you'd rather judge yourself.

### Limits

- `.glb` (binary glTF) only. Every AI generator and every DCC tool
  exports it; single-file `.gltf` with external buffers is not
  accepted.
- Batch zips: up to 100 models per run.
- Renders show static meshes (no animation playback yet).

Built by a game developer who got tired of importing mystery models
one at a time to find out which ones were 40 meters tall.

# Actor input Schema

## `modelUrl` (type: `string`):

Direct link to a .glb file (binary glTF - what AI generators like Meshy and Tripo export), or a .zip containing up to 100 of them for a batch report.

## `targetPreset` (type: `string`):

Sets the budgets and expected real-world size the model is judged against.

## `renders` (type: `boolean`):

Produce a 4-angle contact sheet and a hero shot alongside the report.

## Actor input object example

```json
{
  "modelUrl": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Duck/glTF-Binary/Duck.glb",
  "targetPreset": "pc_prop",
  "renders": true
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "modelUrl": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Duck/glTF-Binary/Duck.glb"
};

// Run the Actor and wait for it to finish
const run = await client.actor("ocean3d/modelcheck").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "modelUrl": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Duck/glTF-Binary/Duck.glb" }

# Run the Actor and wait for it to finish
run = client.actor("ocean3d/modelcheck").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "modelUrl": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Duck/glTF-Binary/Duck.glb"
}' |
apify call ocean3d/modelcheck --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=ocean3d/modelcheck",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Model Check: Game-Ready GLB/glTF 3D Model Validator",
        "description": "Feed it a GLB model URL, get a game-readiness report: real-world scale sanity, pivot placement, triangle and texture budgets, materials, rig and animation summary. Built for sorting AI-generated models (Meshy, Tripo, etc.) into keepers and junk.",
        "version": "0.1",
        "x-build-id": "x4l8VIwu02mRnICyN"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/ocean3d~modelcheck/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-ocean3d-modelcheck",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/ocean3d~modelcheck/runs": {
            "post": {
                "operationId": "runs-sync-ocean3d-modelcheck",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/ocean3d~modelcheck/run-sync": {
            "post": {
                "operationId": "run-sync-ocean3d-modelcheck",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "modelUrl"
                ],
                "properties": {
                    "modelUrl": {
                        "title": "Model URL (.glb or .zip of .glb files)",
                        "type": "string",
                        "description": "Direct link to a .glb file (binary glTF - what AI generators like Meshy and Tripo export), or a .zip containing up to 100 of them for a batch report."
                    },
                    "targetPreset": {
                        "title": "What is this model supposed to be?",
                        "enum": [
                            "mobile_prop",
                            "pc_prop",
                            "character",
                            "hero_asset",
                            "report_only"
                        ],
                        "type": "string",
                        "description": "Sets the budgets and expected real-world size the model is judged against.",
                        "default": "pc_prop"
                    },
                    "renders": {
                        "title": "Render turnaround images",
                        "type": "boolean",
                        "description": "Produce a 4-angle contact sheet and a hero shot alongside the report.",
                        "default": true
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
