It looks like it would be easy to add a texture to a material using Python, but no matter what i do i cant figure it out!

I can create a texture using:

bpy.data.textures.new("NewTexture", type='IMAGE')

and I can create a new material texture slot:


However i can't link the texture to the Material Slot Texture. I have tried looking through the python API but nothing is working. I would be eternal grateful if someone could point me in the right direction.

  • $\begingroup$ What render engine are you using? Internal? $\endgroup$
    – p2or
    Mar 10, 2016 at 13:04
  • $\begingroup$ I was using the blender internal to automatically find the basecolor, roughness, and normal channels to quickly create a game ready material so i could see how the models look before i bring them into the game engine. $\endgroup$ Mar 12, 2016 at 1:04

2 Answers 2


Similar to material_slot.material, there is a texture_slot.texture

(I'm assuming Blender internal from the texture_slots.add in q)

mat = bpy.data.materials['Material']
tex = bpy.data.textures.new("SomeName", 'IMAGE')
slot = mat.texture_slots.add()
slot.texture = tex

A simple example using Cycles can be found here https://blender.stackexchange.com/a/14115/15543

  • 1
    $\begingroup$ You are awesome! That was exactly what i was looking for and it worked. Thanks for the link to the Cycles as well $\endgroup$ Mar 11, 2016 at 4:31
  • 2
    $\begingroup$ That doesn't work in 2.8. There is not material.texture_slots anymore. There is now both material.texture_paint_images and material.texture_paint_slots, but both don't have an add() method. No idea so far how the 2.8 equivalent should look like. $\endgroup$
    – bluenote10
    Oct 10, 2019 at 8:56
  • 5
    $\begingroup$ I have found this question which covers that. $\endgroup$
    – bluenote10
    Oct 10, 2019 at 10:40
  • $\begingroup$ @bluenote10 Thank you so much! I was stuck here. PS THE ABOVE ANSWER IS WRONG FOR BLENDER 2.8. $\endgroup$
    – Bob Denny
    May 1, 2020 at 0:07
  • $\begingroup$ ... surprising that an answer from 2016 aimed at blender internal render engine doesn't work in 2.8. Thanks for the heads up. $\endgroup$
    – batFINGER
    May 1, 2020 at 4:13

The following solution works for Blender 3.0

import bpy
import bmesh

mat = bpy.context.active_object.material_slots[0].material

imgpath = '/image path'
img = bpy.data.images.load(imgpath)


#setup the node_tree and links as you would manually on shader Editor
#to define an image texture for a material

material_output = mat.node_tree.nodes.get('Material Output')
principled_BSDF = mat.node_tree.nodes.get('Principled BSDF')

tex_node = mat.node_tree.nodes.new('ShaderNodeTexImage')
tex_node.image = img

mat.node_tree.links.new(tex_node.outputs[0], principled_BSDF.inputs[0])

#grab mesh data for the active mesh.
mesh = bpy.context.active_object.data
bm = bmesh.from_edit_mesh(bpy.context.object.data)
uv_layer = bm.loops.layers.uv.active

#assign the uv values for the vertices of each face. This example
#assumes the default cube
for i in range(6):

    loop_data = bm.faces[i].loops
    uv_data = loop_data[0][uv_layer].uv
    uv_data.x = 1.0
    uv_data.y = 0.0

    uv_data = loop_data[1][uv_layer].uv
    uv_data.x = 1.0
    uv_data.y = 1.0

    uv_data = loop_data[2][uv_layer].uv
    uv_data.x = 0.0
    uv_data.y = 1.0

    uv_data = loop_data[3][uv_layer].uv
    uv_data.x = 0.0
    uv_data.y = 0.0



You must log in to answer this question.

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