bpy-vrm-format

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.
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.9.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| bpy_vrm_format-4.9.1.tar.gz | 1.6 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bpy_vrm_format-4.9.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 3.2 MB
Release files / bpy_vrm_format-4.9.1.tar.gz
| Download URL | bpy_vrm_format-4.9.1.tar.gz |
|---|---|
| Size | 1.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
65766862f9ca23b2b94457d7631fcd36c39e305e4be2a85c348f929dce981f5e
|
|
BLAKE2b-256 checksum How to use checksums |
da01bd2ca1361f07bf1b1c5c4bf1cf15afdc72894be00c64b3d730b1b4d98adf
|
| 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 Sep 28, 2026.
Transparency logRelease files / bpy_vrm_format-4.9.1-py3-none-any.whl
| Download URL | bpy_vrm_format-4.9.1-py3-none-any.whl |
|---|---|
| Size | 1.6 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
558e7665be781e574794efc951d2102afab7fb761ffc47d493bfa467f655ff4c
|
|
BLAKE2b-256 checksum How to use checksums |
d15597b673fed104fa7640c45d1c4fcfa252ac1b0f7ac5292b5063efbdf6de51
|
| 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 Sep 28, 2026.
Transparency log