Skip to main content

bpy-vrm-format CI status CodSpeed Badge

bpy-vrm-format is a library for working with VRM files, a format for 3D humanoid avatars. It is derived from VRM Add-on for Blender and provides the same API without requiring an installation of Blender itself.

Sample Code for Generating VRM Files

The following sample code generates the 3D character model shown below and saves it as a .vrm file.

VRM model preview

View the 3D model

Before running the script, install the package using pip install bpy-vrm-format or add it to your project using uv add bpy-vrm-format.

from pathlib import Path

import bpy

# Initialize

bpy.ops.preferences.addon_enable(module="io_scene_vrm")

# Create an armature

armature_data = bpy.data.armatures.new("Armature")
armature_object = bpy.data.objects.new("Armature", armature_data)
bpy.context.scene.collection.objects.link(armature_object)
bpy.context.view_layer.objects.active = armature_object

bpy.ops.object.mode_set(mode="EDIT")

hips_bone = armature_data.edit_bones.new("hips")
hips_bone.head = (0, 0, 0.5)
hips_bone.tail = (0, 1, 0.5)
hips_bone_name = hips_bone.name

right_upper_leg_bone = armature_data.edit_bones.new("upper_leg.R")
right_upper_leg_bone.head = (-0.125, 0, 0.5)
right_upper_leg_bone.tail = (-0.125, 1, 0.5)
right_upper_leg_bone.parent = hips_bone
right_upper_leg_bone_name = right_upper_leg_bone.name

right_lower_leg_bone = armature_data.edit_bones.new("lower_leg.R")
right_lower_leg_bone.head = (-0.125, 0, 0.25)
right_lower_leg_bone.tail = (-0.125, 1, 0.25)
right_lower_leg_bone.parent = right_upper_leg_bone
right_lower_leg_bone_name = right_lower_leg_bone.name

right_foot_bone = armature_data.edit_bones.new("foot.R")
right_foot_bone.head = (-0.125, 0, 0)
right_foot_bone.tail = (-0.125, 1, 0)
right_foot_bone.parent = right_lower_leg_bone
right_foot_bone_name = right_foot_bone.name

left_upper_leg_bone = armature_data.edit_bones.new("upper_leg.L")
left_upper_leg_bone.head = (0.125, 0, 0.5)
left_upper_leg_bone.tail = (0.125, 1, 0.5)
left_upper_leg_bone.parent = hips_bone
left_upper_leg_bone_name = left_upper_leg_bone.name

left_lower_leg_bone = armature_data.edit_bones.new("lower_leg.L")
left_lower_leg_bone.head = (0.125, 0, 0.25)
left_lower_leg_bone.tail = (0.125, 1, 0.25)
left_lower_leg_bone.parent = left_upper_leg_bone
left_lower_leg_bone_name = left_lower_leg_bone.name

left_foot_bone = armature_data.edit_bones.new("foot.L")
left_foot_bone.head = (0.125, 0, 0)
left_foot_bone.tail = (0.125, 1, 0)
left_foot_bone.parent = left_lower_leg_bone
left_foot_bone_name = left_foot_bone.name

spine_bone = armature_data.edit_bones.new("spine")
spine_bone.head = (0, 0, 0.625)
spine_bone.tail = (0, 1, 0.625)
spine_bone.parent = hips_bone
spine_bone_name = spine_bone.name

right_upper_arm_bone = armature_data.edit_bones.new("upper_arm.R")
right_upper_arm_bone.head = (-0.125, 0, 0.75)
right_upper_arm_bone.tail = (-0.125, 1, 0.75)
right_upper_arm_bone.parent = spine_bone
right_upper_arm_bone_name = right_upper_arm_bone.name

right_lower_arm_bone = armature_data.edit_bones.new("lower_arm.R")
right_lower_arm_bone.head = (-0.25, 0, 0.75)
right_lower_arm_bone.tail = (-0.25, 1, 0.75)
right_lower_arm_bone.parent = right_upper_arm_bone
right_lower_arm_bone_name = right_lower_arm_bone.name

right_hand_bone = armature_data.edit_bones.new("hand.R")
right_hand_bone.head = (-0.375, 0, 0.75)
right_hand_bone.tail = (-0.375, 1, 0.75)
right_hand_bone.parent = right_lower_arm_bone
right_hand_bone_name = right_hand_bone.name

left_upper_arm_bone = armature_data.edit_bones.new("upper_arm.L")
left_upper_arm_bone.head = (0.125, 0, 0.75)
left_upper_arm_bone.tail = (0.125, 1, 0.75)
left_upper_arm_bone.parent = spine_bone
left_upper_arm_bone_name = left_upper_arm_bone.name

left_lower_arm_bone = armature_data.edit_bones.new("lower_arm.L")
left_lower_arm_bone.head = (0.25, 0, 0.75)
left_lower_arm_bone.tail = (0.25, 1, 0.75)
left_lower_arm_bone.parent = left_upper_arm_bone
left_lower_arm_bone_name = left_lower_arm_bone.name

left_hand_bone = armature_data.edit_bones.new("hand.L")
left_hand_bone.head = (0.375, 0, 0.75)
left_hand_bone.tail = (0.375, 1, 0.75)
left_hand_bone.parent = left_lower_arm_bone
left_hand_bone_name = left_hand_bone.name

head_bone = armature_data.edit_bones.new("head")
head_bone.head = (0, 0, 0.75)
head_bone.tail = (0, 1, 0.75)
head_bone.parent = spine_bone
head_bone_name = head_bone.name

bpy.ops.object.mode_set(mode="OBJECT")

# Assign VRM human bones

humanoid = armature_data.vrm_addon_extension.vrm1.humanoid
humanoid.human_bones.head.node.bone_name = head_bone_name
humanoid.human_bones.spine.node.bone_name = spine_bone_name
humanoid.human_bones.hips.node.bone_name = hips_bone_name
humanoid.human_bones.right_upper_arm.node.bone_name = right_upper_arm_bone_name
humanoid.human_bones.right_lower_arm.node.bone_name = right_lower_arm_bone_name
humanoid.human_bones.right_hand.node.bone_name = right_hand_bone_name
humanoid.human_bones.left_upper_arm.node.bone_name = left_upper_arm_bone_name
humanoid.human_bones.left_lower_arm.node.bone_name = left_lower_arm_bone_name
humanoid.human_bones.left_hand.node.bone_name = left_hand_bone_name
humanoid.human_bones.right_upper_leg.node.bone_name = right_upper_leg_bone_name
humanoid.human_bones.right_lower_leg.node.bone_name = right_lower_leg_bone_name
humanoid.human_bones.right_foot.node.bone_name = right_foot_bone_name
humanoid.human_bones.left_upper_leg.node.bone_name = left_upper_leg_bone_name
humanoid.human_bones.left_lower_leg.node.bone_name = left_lower_leg_bone_name
humanoid.human_bones.left_foot.node.bone_name = left_foot_bone_name

# Add meshes

bpy.ops.mesh.primitive_uv_sphere_add(radius=0.25)
head = bpy.context.active_object
head.parent = armature_object
head.parent_bone = humanoid.human_bones.head.node.bone_name
head.parent_type = "BONE"

bpy.ops.mesh.primitive_cube_add(size=0.4)
spine = bpy.context.active_object
spine.parent = armature_object
spine.parent_bone = humanoid.human_bones.spine.node.bone_name
spine.parent_type = "BONE"

bpy.ops.mesh.primitive_ico_sphere_add(radius=0.1)
left_upper_arm = bpy.context.active_object
left_upper_arm.parent = armature_object
left_upper_arm.parent_bone = humanoid.human_bones.left_upper_arm.node.bone_name
left_upper_arm.parent_type = "BONE"

bpy.ops.mesh.primitive_ico_sphere_add(radius=0.1)
left_hand = bpy.context.active_object
left_hand.parent = armature_object
left_hand.parent_bone = humanoid.human_bones.left_hand.node.bone_name
left_hand.parent_type = "BONE"

bpy.ops.mesh.primitive_ico_sphere_add(radius=0.1)
right_upper_arm = bpy.context.active_object
right_upper_arm.parent = armature_object
right_upper_arm.parent_bone = humanoid.human_bones.right_upper_arm.node.bone_name
right_upper_arm.parent_type = "BONE"

bpy.ops.mesh.primitive_ico_sphere_add(radius=0.1)
right_hand = bpy.context.active_object
right_hand.parent = armature_object
right_hand.parent_bone = humanoid.human_bones.right_hand.node.bone_name
right_hand.parent_type = "BONE"

bpy.ops.mesh.primitive_ico_sphere_add(radius=0.1)
left_upper_leg = bpy.context.active_object
left_upper_leg.parent = armature_object
left_upper_leg.parent_bone = humanoid.human_bones.left_upper_leg.node.bone_name
left_upper_leg.parent_type = "BONE"

bpy.ops.mesh.primitive_ico_sphere_add(radius=0.1)
right_upper_leg = bpy.context.active_object
right_upper_leg.parent = armature_object
right_upper_leg.parent_bone = humanoid.human_bones.right_upper_leg.node.bone_name
right_upper_leg.parent_type = "BONE"

bpy.ops.mesh.primitive_ico_sphere_add(radius=0.1)
left_lower_leg = bpy.context.active_object
left_lower_leg.parent = armature_object
left_lower_leg.parent_bone = humanoid.human_bones.left_lower_leg.node.bone_name
left_lower_leg.parent_type = "BONE"

bpy.ops.mesh.primitive_ico_sphere_add(radius=0.1)
right_lower_leg = bpy.context.active_object
right_lower_leg.parent = armature_object
right_lower_leg.parent_bone = humanoid.human_bones.right_lower_leg.node.bone_name
right_lower_leg.parent_type = "BONE"

# Set metadata

meta = armature_data.vrm_addon_extension.vrm1.meta
meta.vrm_name = "Your Model Name"
meta.version = "1.0.0"

# Save to a file

output_filepath = str(Path(__file__).parent / "path_to_your_vrm_model.vrm")
result = bpy.ops.export_scene.vrm(filepath=output_filepath)
if result != {"FINISHED"}:
    message = f"Failed to export vrm: {result}"
    raise RuntimeError(message)

print(f'Saved the VRM file to "{output_filepath}"')

For more information, see the Scripting API documentation.

Metadata

Release files for bpy-vrm-format 4.10.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bpy-vrm-format 4.10.1
File Size Uploaded
bpy_vrm_format-4.10.1.tar.gz 1.6 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for bpy-vrm-format 4.10.1
File Interpreter ABI Platform
bpy_vrm_format-4.10.1-py3-none-any.whl Python 3 none any Details

Total release size: 3.2 MB

Release files / bpy_vrm_format-4.10.1.tar.gz

Download URL bpy_vrm_format-4.10.1.tar.gz
Size 1.6 MB
Tags Source
SHA-256 checksum
How to use checksums
6ff060cc184abe43b208c80c8a3cc9c2a871c3b78eb5f9cadd8930479a19dbfa
BLAKE2b-256 checksum
How to use checksums
977fd047cddb5ee85e4cf9aea8f23fce82901bd5efd90381e168a99d8682b682
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / bpy_vrm_format-4.10.1-py3-none-any.whl

Download URL bpy_vrm_format-4.10.1-py3-none-any.whl
Size 1.6 MB
Tags Python 3
SHA-256 checksum
How to use checksums
70e645c1e6bb7a08f1eb8d028bda59da183c85c8554c93873eaef80438bbeae4
BLAKE2b-256 checksum
How to use checksums
cf4dea808756e7d13e94c514d20012e4f30b9e18c0be9ce1afe2d9b133e35df6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release history Release notifications | RSS feed

4.10.2

2 release files

This release

4.10.1 This release

2 release files

4.10.0

2 release files

4.9.1

2 release files

4.9.0

2 release files

4.8.0

2 release files

4.7.4

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page