Blender's addon system is one of the most accessible entry points into tool development for 3D artists. If you know basic Python and use Blender regularly, you have everything you need to start building custom tools that solve your specific workflow problems.
This guide walks through the complete process of creating a Blender addon in 2026 — from understanding the API to packaging and distributing your finished tool. We will build a simple but functional addon along the way so every concept has a concrete example.
Why Build Blender Addons
The practical reasons:
- Automate repetitive tasks. If you do the same sequence of clicks 50 times a day, an addon can do it in one click.
- Customize Blender to your pipeline. Studios and indie developers have specific workflows that generic tools do not cover.
- Share tools with your team. Package your automation as an addon that anyone on your team can install.
- Contribute to the community. Blender's ecosystem thrives on community addons. Your niche tool might solve a problem thousands of others have.
Prerequisites
You need:
- Blender 4.2+ (this guide targets the current LTS and 4.x releases)
- Basic Python knowledge. Variables, functions, classes, loops. You do not need to be an expert.
- A text editor. VS Code with the Blender Development extension is the best setup, but Blender's built-in text editor works for learning.
Blender's Python API: The Basics
Blender exposes nearly its entire functionality through Python. Open Blender's Python console (Editor Type > Python Console) and try:
import bpy
# Get the active object
obj = bpy.context.active_object
print(obj.name)
# Move it
obj.location.x += 1.0
# List all objects in the scene
for obj in bpy.data.objects:
print(obj.name, obj.type)
The three most important modules:
bpy.context— The current state: active object, selected objects, current mode, active scene.bpy.data— All data in the file: objects, meshes, materials, images, scenes.bpy.ops— Operators (actions):bpy.ops.mesh.subdivide(),bpy.ops.object.delete(), etc.
The Info Editor Trick
Blender logs every operation as a Python command in the Info editor. Perform an action in the UI, then check the Info editor to see the exact Python call. This is the fastest way to learn which API calls correspond to which UI actions.
Addon Structure
A Blender addon is a Python file (or package) with a specific structure. Here is the minimal template:
bl_info = {
"name": "My First Addon",
"author": "Your Name",
"version": (1, 0, 0),
"blender": (4, 2, 0),
"location": "View3D > Sidebar > My Addon",
"description": "A simple example addon",
"category": "Object",
}
import bpy
class MYADDON_OT_simple_operator(bpy.types.Operator):
"""Tooltip description for this operator"""
bl_idname = "myaddon.simple_operator"
bl_label = "Do Something"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
self.report({'INFO'}, "Operator executed!")
return {'FINISHED'}
class MYADDON_PT_main_panel(bpy.types.Panel):
bl_label = "My Addon"
bl_idname = "MYADDON_PT_main_panel"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = "My Addon"
def draw(self, context):
layout = self.layout
layout.operator("myaddon.simple_operator")
classes = (
MYADDON_OT_simple_operator,
MYADDON_PT_main_panel,
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
if __name__ == "__main__":
register()
The bl_info Dictionary
This metadata block tells Blender about your addon. Required fields:
- name: Display name in Preferences > Add-ons
- blender: Minimum Blender version as a tuple
- category: Where it appears in the addon list (Object, Mesh, Material, Render, etc.)
Naming Conventions
Blender enforces strict naming for classes:
- Operators:
ADDONNAME_OT_operator_name - Panels:
ADDONNAME_PT_panel_name - Menus:
ADDONNAME_MT_menu_name - Properties:
ADDONNAME_PG_property_group
The prefix must be uppercase, followed by the type code (OT, PT, MT, PG), followed by the name. Using consistent prefixes prevents naming collisions with other addons.
register() and unregister()
Every addon must have these two functions. register() is called when the addon is enabled. unregister() is called when it is disabled. They must properly register and unregister all classes and any properties you add to Blender's data.
Creating Operators
Operators are the core of Blender addons — they perform actions. Every button click in Blender calls an operator.
Operator with Properties
You can add properties to operators that appear in the operator's UI:
class MYADDON_OT_scale_objects(bpy.types.Operator):
"""Scale all selected objects by a uniform factor"""
bl_idname = "myaddon.scale_objects"
bl_label = "Scale Selected"
bl_options = {'REGISTER', 'UNDO'}
scale_factor: bpy.props.FloatProperty(
name="Scale Factor",
default=1.5,
min=0.1,
max=10.0,
description="Uniform scale multiplier"
)
@classmethod
def poll(cls, context):
return context.selected_objects
def execute(self, context):
for obj in context.selected_objects:
obj.scale *= self.scale_factor
self.report(
{'INFO'},
f"Scaled {len(context.selected_objects)} objects "
f"by {self.scale_factor}"
)
return {'FINISHED'}
Key elements:
poll(): Determines when the operator is available. If it returns False, the button is grayed out. Here it requires at least one selected object.execute(): The main logic. Returns{'FINISHED'}on success or{'CANCELLED'}on failure.- Properties:
FloatProperty,IntProperty,BoolProperty,StringProperty,EnumProperty— these create UI controls automatically when the operator runs.
Operator with Invoke (Dialog)
For operators that need user input before executing:
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self)
This opens a dialog showing the operator's properties before execution.
Building N-Panel UIs
The sidebar (N-Panel) is the standard location for addon UIs. You create panels by subclassing bpy.types.Panel:
class MYADDON_PT_settings_panel(bpy.types.Panel):
bl_label = "Settings"
bl_idname = "MYADDON_PT_settings_panel"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = "My Addon"
bl_parent_id = "MYADDON_PT_main_panel" # Makes this a sub-panel
def draw(self, context):
layout = self.layout
scene = context.scene
# Add UI elements
layout.label(text="Configuration:")
layout.prop(scene, "my_addon_setting")
row = layout.row(align=True)
row.operator("myaddon.scale_objects", text="Scale Up").scale_factor = 2.0
row.operator("myaddon.scale_objects", text="Scale Down").scale_factor = 0.5
layout.separator()
box = layout.box()
box.label(text="Advanced", icon='PREFERENCES')
box.prop(scene, "my_addon_advanced_setting")
Layout elements: layout.row(), layout.column(), layout.box(), layout.split(), layout.separator(). These compose to create structured UIs without any CSS or HTML.
Storing Addon Settings
Use PropertyGroup to store settings on the scene or window manager:
class MYADDON_PG_settings(bpy.types.PropertyGroup):
output_path: bpy.props.StringProperty(
name="Output Path",
subtype='DIR_PATH',
default="//"
)
resolution: bpy.props.EnumProperty(
name="Resolution",
items=[
('1024', "1024", "1024x1024"),
('2048', "2048", "2048x2048"),
('4096', "4096", "4096x4096"),
],
default='2048'
)
def register():
# ... register classes ...
bpy.types.Scene.my_addon = bpy.props.PointerProperty(
type=MYADDON_PG_settings
)
def unregister():
del bpy.types.Scene.my_addon
# ... unregister classes ...
Access settings in operators via context.scene.my_addon.resolution.
Working with Materials Programmatically
Material scripting is one of the most useful addon capabilities. Here is how to create and modify materials via Python:
def create_pbr_material(name, base_color, roughness=0.5, metallic=0.0):
"""Create a Principled BSDF material with given parameters."""
mat = bpy.data.materials.new(name=name)
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links
# Clear default nodes
nodes.clear()
# Create Principled BSDF
bsdf = nodes.new('ShaderNodeBsdfPrincipled')
bsdf.location = (0, 0)
bsdf.inputs['Base Color'].default_value = (*base_color, 1.0)
bsdf.inputs['Roughness'].default_value = roughness
bsdf.inputs['Metallic'].default_value = metallic
# Create output
output = nodes.new('ShaderNodeOutputMaterial')
output.location = (300, 0)
links.new(bsdf.outputs['BSDF'], output.inputs['Surface'])
return mat
You can add texture nodes, noise textures, color ramps, and any other shader node the same way — nodes.new('ShaderNodeTexNoise'), set parameters, create links with links.new().
Multi-File Addon Structure
As your addon grows, split it into a Python package:
my_addon/
__init__.py # bl_info, register(), unregister()
operators.py # Operator classes
panels.py # Panel classes
properties.py # PropertyGroup classes
utils.py # Helper functions
The __init__.py imports from the other modules and handles registration.
Packaging for Distribution
For Blender 4.2+ (Extension Platform)
Blender 4.2 introduced the Extensions platform with a new manifest format. Create a blender_manifest.toml file in your addon directory:
schema_version = "1.0.0"
id = "my_first_addon"
version = "1.0.0"
name = "My First Addon"
tagline = "A simple example addon"
maintainer = "Your Name <your@email.com>"
type = "add-on"
# Blender version requirements
blenders = [">=4.2.0"]
# License (SPDX identifier)
license = ["GPL-3.0-or-later"]
# Optional
website = "https://your-website.com"
category = "Object"
Package your addon as a .zip file containing the addon directory and the manifest. Users install it through Edit > Preferences > Get Extensions, or by dragging the zip into Blender.
For Older Blender Versions
For Blender versions before 4.2, the bl_info dictionary in __init__.py is the metadata source. Package as a .zip containing the addon directory. Install via Edit > Preferences > Add-ons > Install.
Supporting Both
Include both bl_info in __init__.py and blender_manifest.toml in the package root. Blender 4.2+ will use the manifest; older versions will use bl_info.
Debugging Tips
- Blender's Python Console is your REPL. Test snippets before putting them in your addon.
print()statements appear in Blender's system console (Window > Toggle System Console on Windows, or launch Blender from terminal on Linux/macOS).self.report({'ERROR'}, "message")in operators shows errors in the Blender UI status bar.- Reload scripts with F3 > "Reload Scripts" or by disabling/re-enabling your addon in Preferences.
- VS Code + Blender Development extension: Set breakpoints, step through code, and get autocomplete for the bpy API.
Resources for Learning
- Blender Python API Documentation: docs.blender.org/api/current — The definitive reference. Dense but complete.
- Blender's Built-in Templates: File > New > General, then in the Text Editor: Templates > Python > Operator, UI Panel, etc. These are official starter templates.
- Blender Source Code: Blender's own built-in addons (in the
addonsdirectory of your Blender installation) are excellent examples of production-quality addon code. - Blender Artists Forum: Active community for addon development questions and feedback.
- Blender Extensions Platform: Browse existing addons to see how others structure their code.
Next Steps
Once you are comfortable with the basics:
- Build a tool you actually need. The best first addon solves a real problem in your own workflow.
- Study existing addons. Download popular addons and read their source code. See how they handle complex UIs, file I/O, and error cases.
- Learn Geometry Nodes scripting. The Python API for Geometry Nodes is a powerful way to build procedural tools.
- Explore batch processing. Addons that operate on multiple objects or files at once are some of the most time-saving tools you can build.
The Blender addon ecosystem in 2026 is mature and welcoming. The API is well-documented, the community is active, and the new Extensions platform makes distribution straightforward. Your workflow frustration is probably someone else's too — build the solution and share it.