Quickstart Introduction



The Blender/Python API can do the following:

  • Modify user preferences, keymaps and themes
  • Run tools with own settings
  • Create user interface elements such as menus, headers and panels
  • Create new tools
  • Create interactive tools
  • Create new rendering engines that integrate with Blender
  • Define new settings in existing Blender data
  • Draw in the 3D view using OpenGL commands from Python

The Blender/Python API can’t (yet)...

  • Create new space types.
  • Assign custom properties to every type.

Before Starting


A quick list of helpful things to know before starting:

  • Blender uses Python 3.x; some online documentation still assumes 2.x.

  • The interactive console is great for testing one-liners. It also has autocompletion so you can inspect the API quickly.

  • Button tool tips show Python attributes and operator names.



  • To examine further scripts distributed with Blender, see:

    ~/.blender/scripts/startup/bl_ui for the user interface,

Running Scripts

The two most common ways to execute Python scripts are using the built-in text editor or entering commands in the Python console.

Both the Text Editor and Python Console are space types you can select from the view header.

Rather then manually configuring your spaces for Python development, you may prefer to use the Scripting screen, included default with Blender, accessible from the top headers screen selector.

From the text editor you can open .py files or paste then from the clipboard, then test using Run Script.

The Python Console is typically used for typing in snippets and for testing to get immediate feedback, but can also have entire scripts pasted into it.

Scripts can also run from the command line with Blender but to learn Blender/Python this isn’t essential.

Key Concepts

Data Access

Accessing DataBlocks



>>> bpy.data.objects
<bpy_collection[3], BlendDataObjects>
>>> bpy.data.scenes
<bpy_collection[1], BlendDataScenes>
>>> bpy.data.materials
<bpy_collection[1], BlendDataMaterials>

About Collections



>>> list(bpy.data.objects)
>>> bpy.data.objects['Cube']
>>> bpy.data.objects[0]

Accessing Attributes


>>> bpy.data.objects[0].name
>>> bpy.data.scenes["Scene"]
>>> bpy.data.materials.new("MyMaterial")



>>> bpy.data.scenes[0].render.resolution_percentage

Data Creation/Removal

Those of you familiar with other Python API’s may be surprised that new datablocks in the bpy API can’t be created by calling the class:

>>> bpy.types.Mesh()
Traceback (most recent call last):

This is an intentional part of the API design. The Blender/Python API can’t create Blender data that exists outside the main Blender database (accessed through bpy.data), because this data is managed by Blender (save/load/undo/append... etc).


>>> print(mesh)
<bpy_struct, Mesh("MyMesh.001")>
>>> bpy.data.meshes.remove(mesh)

Custom Properties




bpy.context.object["MyOwnProperty"] = 42

if "SomeProp" in bpy.context.object:
    print("Property found")

# Use the get function like a Python dictionary
# which can have a fallback value.

group = bpy.data.groups.new("MyTestGroup")

del group["GameSettings"]

Note that these properties can only be assigned basic Python types.

  • int, float, string
  • array of ints/floats



While it’s useful to be able to access data directly by name or as a list, it’s more common to operate on the user’s selection. The context is always available from bpy.context and can be used to get the active object, scene, tool settings along with many other attributes.

Common-use cases:

>>> bpy.context.object
>>> bpy.context.selected_objects
>>> bpy.context.visible_bones


So bpy.context.object = obj will raise an error.

But bpy.context.scene.objects.active = obj will work as expected.


See bpy.context API reference.

Operators (Tools)



>>> bpy.ops.mesh.flip_normals()
>>> bpy.ops.mesh.hide(unselected=False)
>>> bpy.ops.object.scale_apply()


The menu item: Help ‣ Operator Cheat Sheet gives a list of all operators and their default values in Python syntax, along with the generated docs. This is a good way to get an overview of all Blender’s operators.

Operator Poll()

Many operators have a “poll” function which may check that the cursor is in a valid area or that the object is in the correct mode (Edit Mode, Weight Paint etc). When an operator’s poll function fails within Python, an exception is raised.


RuntimeError: Operator bpy.ops.view3d.render_border.poll() failed, context is incorrect


To avoid using try/except clauses wherever operators are called you can call the operators own poll() function to check if it can run in the current context.

if bpy.ops.view3d.render_border.poll():


Python scripts can integrate with Blender in the following ways:

  • By defining a rendering engine.
  • By defining operators.
  • By defining menus, headers and panels.
  • By inserting new buttons into existing menus, headers and panels


Example Operator

import bpy

def main(context):
    for ob in context.scene.objects:

class SimpleOperator(bpy.types.Operator):
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"

    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        return {'FINISHED'}

def register():

def unregister():

if __name__ == "__main__":

    # test call


To run the script:

  1. Highlight the above code then press Ctrl-C to copy it.
  2. Start Blender
  3. Press Ctrl-Right twice to change to the Scripting layout.
  5. Press Ctrl-V to paste the code into the text panel (the upper left frame).
  6. Click on the button Run Script.
  7. Move your cursor into the 3D view, press spacebar for the operator search menu, and type “Simple”.

See also




Example Panel


import bpy

class HelloWorldPanel(bpy.types.Panel):
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        layout = self.layout

        obj = context.object

        row = layout.row()

        row = layout.row()
        row = layout.row()
        row.prop(obj, "name")

        row = layout.row()

def register():

def unregister():

if __name__ == "__main__":

To run the script:

  2. Start Blender
  6. Click on the button Run Script.

To view the results:

  1. Select the the default cube.


See also




Blender’s Python API can be split up into 3 categories.

Native Types

In simple cases returning a number or a string as a custom type would be cumbersome, so these are accessed as normal Python types.

  • Blender float/int/boolean -> float/int/boolean

  • Blender enumerator -> string

    >>> C.object.rotation_mode = 'AXIS_ANGLE'
  • Blender enumerator (multiple) -> set of strings

    # setting multiple camera overlay guides
    bpy.context.scene.camera.data.show_guide = {'GOLDEN', 'CENTER'}
    # passing as an operator argument for report types

Internal Types

Used for Blender datablocks and collections: bpy.types.bpy_struct



>>> bpy.context.object
>>> C.scene.objects


Mathutils Types



Example of a matrix, vector multiplication:

bpy.context.object.matrix_world * bpy.context.object.data.verts[0].co




# modifies the Z axis in place.
bpy.context.object.location.z += 2.0

# location variable holds a reference to the object too.
location = bpy.context.object.location
location *= 2.0

# functions and modified without unwanted side effects.
location = bpy.context.object.location.copy()


There are 2 ways to add keyframes through Python.


Both examples insert a keyframe on the active object’s Z axis.

Simple example:

obj = bpy.context.object
obj.location[2] = 0.0
obj.location[2] = 1.0

Using Low-Level Functions:

obj = bpy.context.object
obj.animation_data.action = bpy.data.actions.new(name="MyAction")
fcu_z.keyframe_points[0].co = 10.0, 0.0
fcu_z.keyframe_points[1].co = 20.0, 1.0