In Blender/Python 2.8, I can't get my code to create the surface node I want (it creates a shader node along with a surface node that I don't want). The objective is to assign an image texture to an object as seen in three related posts (1, 2 and 3):

The manual process produces the desired result by setting up the node as follows: Surface node Diffuse BSDF

In Python I am attempting to do the same (code below), but the results aren't working out. First I'll show the output, then the code:

Here's the objectionable output:

enter image description here

And here's the node tree as created by my code; when I make the manual adjustments I note in the picture I get the final result that I want:

enter image description here

My flawed code is below. Before you criticize the obvious problem (that I am creating shaders), I have tried other approaches (replacing "Shader" with "Surface" and various other words) without success. I am also baffled as to why the "Principled BSDF" node appears out of nowhere.

Here's my code. Your suggestions would be highly appreciated. Thanks in advance!

matP = bpy.data.materials.get(matP_name)
if matP is None:
    matP = bpy.data.materials.new(matP_name)
nodes = matP.node_tree.nodes
diffuse_BSDF = matP.node_tree.nodes.new(nodeID)
imgTex = bpy.data.images.load(path)
node_texture = nodes.new(type='ShaderNodeTexImage')
node_texture.image = imgTex
node_texture.location = 0,200
links = matP.node_tree.links
link = links.new(node_texture.outputs[0], nodes.get('Diffuse BSDF').inputs[0])
  • 2
    $\begingroup$ If I read correctly this code does not link the diffuse to the output. Also creating a new material will create principled and output by default. So you need to clear them. material.node_tree.links.clear() material.node_tree.nodes.clear() $\endgroup$
    – lemon
    Jul 29, 2019 at 16:02
  • $\begingroup$ @lemon Doesn't this create the link? link = links.new(node_texture.outputs[0], nodes.get('Diffuse BSDF').inputs[0]) $\endgroup$
    – vndep
    Jul 29, 2019 at 16:11
  • 1
    $\begingroup$ Yes but between texture and diffuse, not between diffuse and output $\endgroup$
    – lemon
    Jul 29, 2019 at 16:11
  • $\begingroup$ @lemon What python code would link diffuse and output? $\endgroup$
    – vndep
    Jul 29, 2019 at 16:13

1 Answer 1


Small code that can bring the indication you need.

import bpy

# Clear all nodes in a mat
def clear_material( material ):
    if material.node_tree:

# Create a node corresponding to a defined group
def instanciate_group( nodes, group_name ):
    group = nodes.new( type = 'ShaderNodeGroup' )
    group.node_tree = bpy.data.node_groups[group_name]

materials = bpy.data.materials

mat_name = 'test'

material = materials.get( mat_name )

if not material:
    material = materials.new( mat_name )

# We clear it as we'll define it completely
clear_material( material )

material.use_nodes = True

nodes = material.node_tree.nodes
links = material.node_tree.links

output = nodes.new( type = 'ShaderNodeOutputMaterial' )

diffuse = nodes.new( type = 'ShaderNodeBsdfDiffuse' )

#With names
link = links.new( diffuse.outputs['BSDF'], output.inputs['Surface'] )
#Or with indices
#link = links.new( diffuse.outputs[0], output.inputs[0] )

Note: when you create a new material (materials.new(...)), it creates two nodes by default (principled linked to ouput).

  • 1
    $\begingroup$ thanks a lot ... that solves the problem. $\endgroup$
    – vndep
    Jul 29, 2019 at 17:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .