Here is your script (a) doing what I think you want it to do. It makes a mesh object at each frame, and adds a location keyframe at the frame it was created in script. If you are using an operator, need to be in, or set the context it requires. Make a new object `obj` context with `context.scene.objects.active = obj`. If it works on selected objects, like say join, need to make sure other objects are (de)selected correctly by setting `obj.select` accordingly on each. Going to use [`bpy_struct.keyframe_insert(...)`][1] rather than the operator. This will be quicker, especially for high numbers. import bpy from math import sin, cos scn = bpy.context.scene numY = 10 freq = 1 amp = 1 scale = 1 for numX in range (2, 20): verts = [] faces = [] for i in range (0, numX): x = scale * i for j in range (0, numY): y = scale * j z = scale * amp * (cos(i * freq) + sin(j * freq)) vert = (x, y, z) verts.append(vert) count = 0 for i in range (0, numY * (numX - 1)): if count < numY - 1: A = i B = i + 1 C = (i + numY) + 1 D = (i + numY) face = (A, B, C, D) faces.append(face) count = count + 1 else: count = 0 mesh = bpy.data.meshes.new("Wave") mesh.from_pydata(verts, [], faces) mesh.update(calc_edges = True) obj = bpy.data.objects.new("Wave", mesh) obj.location = (0, 0, 0) scn.objects.link(obj) obj.keyframe_insert("location", frame=numX, group="Location") [1]: https://docs.blender.org/api/blender_python_api_current/bpy.types.bpy_struct.html#bpy.types.bpy_struct.keyframe_insert