Really struggling with selection

I haven’t looked closely at the Blender code regarding selection, but in my experience the Blender Python API is just a thin layer on top of the underlying C or C++ code. So when it comes to (say) the set of selected vertices there probably is no explicit object representing that, as I suspect each vertex has an associated flag, just like there’s a select attribute in Python. Meaning: selection is represented implicitly by the per-vertex flag, which is why looping through the set of vertices to get the selection is the way to go. But then again, I might be wrong :wink:

Now, there could be an extra operation in the Python API to make it easier to extract that selection, even when in edit-mode, but there isn’t one apparently. I guess this is an example case of how open-source is different from commercial software. If someone wants a certain feature badly enough and is capable of writing it themselves then such a software patch might get submitted to the Blender source repositories and end up in Blender. I recently had a minor feature I was missing (background rectangles on text items in the video sequencer) get accepted in this way. There simply isn’t a marketing/sales department for Blender that is actively monitoring customer satistifaction, driving the roadmap, etc. The contacts the Blender institute and devs have with the larger studios obviously have influence in this respect, but it’s not the same.

Anyways, more concretely, when in edit-mode you can use a BMesh object and loop through that to get the selection, e.g. in the Python console:

# Having a mesh in edit-mode, with some vertices selected
>>> import bmesh
>>> o = bpy.context.active_object
>>> m =
# Create a BMesh object, mesh m needs to be in edit-mode
>>> bm = bmesh.from_edit_mesh(m)
# Retrieve the selection
>>> [v for v in bm.verts if]
[<BMVert(0x7f6260aae590), index=0>, <BMVert(0x7f6260aae5c8), index=1>]
# After changing the vertex selection on the mesh (still in edit-mode!)
>>> [v for v in bm.verts if]
[<BMVert(0x7f6260aae600), index=2>, <BMVert(0x7f6260aae638), index=3>, <BMVert(0x7f6260aae670), index=4>, <BMVert(0x7f6260aae6e0), index=6>]
# When done clean up the BMesh object
>>> bm
<BMesh dead at 0x7f6262c16f00>

To match up the indices shown with the mesh you would need to enable Developer extras under Preferences > Interface > Display, and then in the Viewport overlay settings (the intersecting balls in the top-right) enable Indices under Developer. Yes, very convoluted. But it probably also reflects that this isn’t a widely used feature (or people just give up trying to get it to work). There might also be better ways to do this that I’m not aware off. Perhaps there’s an addon that makes this easier, although a quick google search just now didn’t turn up one.

Edit: just noticed this overlaps quite a bit with the answers from @Debuk, but perhaps gives you a few more concrete things to use


Nice post @PaulMelis. Thank you.

This resonates with my code spelunking experiences, going on about two years now. I think that probably sums up @CMK_blender’s pain points as well. My past scripting experience with Maya was largely pleasant - my humble opinion here, but I had the sense the Maya scripting environment was meant for me. On the other hand, Blender’s Python API is also meant to support a separation of concerns between a user interface - largely implemented in Python - and core Blender. Oh! yes. People can write add-ons written to this Python interface as well. I’m being a bit sarcastic here, but the sense is that the Python API is not quite meant for me, but, hey - presto! - I can use it if I want to!

At the end of the day, there are (my guess) about a thousand animators wanting decent frame rates so they can effectively judge their work for every script writer wanting a API that’s meant for them. But who was Blender really written for, anyway? animators or script writers?

I should bow out, now, as this entire thread is trending toward a feature request better situated at RCS. But for those who would wish otherwise, the Python API is what it is because it serves multiple purposes; it is not entirely (wholly?) geared to my own preferences for ease-of-use, much as I would wish otherwise. Script writing ease-of-use is not a priority, and I’m OK with that, given who the application was written for and understanding that not everything can be high priority. I humbly work with what is there, as many, many people here seem able to do, and successfully too.

1 Like

I agree with you on this point. But to be fair the Python API really has improved over the years. Although there’s still quite a lot of room for improvement. My pet annoyance with it is that certain operations are only available as operators that run as if they’re called from the UI (e.g. due to a button press). For example, if you want to apply a boolean operation to two meshes you have to script it using an modifier. There’s no Python API call boolean_intersect(mesh1, mesh2) that simply operates on two meshes without worrying about the UI context.

In the beginning Blender was probably mostly written for the same folks that were using it, or at least there was quite a bit of overlap. Looking at the history of the Python API it was introduced with 2.10 in December 2000. The immediate use, judging by the release notes seems to have been to allow scripting in the game engine part of Blender. Since then it has been retargeted to allow defining the UI fully (quite a daring feat) and accessing all kinds of internals. All in all, I’d say it grew organically into what it is now.


Thank you Paul. It must be noted that the Python API has improved and is improving and - perhaps - I was unfairly suggesting that the API is a dark corner of Blender that nobody cares about and is going to dust. That certainly is not the case. It has gotten a lot harder to crash Blender by dropping a bomb on it through the Python API. Instead - very frequently now - I get trace backs telling me that RNA properties have changed and my references are stale. My motivation for the post was to manage expectations for new comers. Of course, I wish for a friendlier API. Who wouldn’t? But if wishes were horses, beggars would ride…

1 Like

God yes, coming from decades in commercial software where it’s possible to do this, I cringe at the thought of it, because it’s incredibly fragile and prone to breaking. It’s very bad practice which generally only people who are new to scripting resort to.

This is part of why I started this thread. I’m relatively new to Blender, and so am bumping my way in the dark, and I felt like doing it this way was exactly the same sort of thing. It’s a bit shocking to hear that there isn’t an alternative. E.g., the selection-by-looping-specific-components approach. It is exactly what I came up with, myself, but it felt so limited, covoluted, and wrong, that I figured there had to be another way.

Again, shocking to learn there is not.

1 Like

This is so much like my dive in to Blender. Right away I couldn’t stand how clunky selection behavior was in general so I set out looking for way to make it behave in a way that felt more intuitive and comfortable to me. I ran in to a lot of the issues you’re talking about where just getting Blender to tell you what’s selected became a massive headache.

I basically started writing my own selection operators in python and got decently far along before 2.8 came along and broke all my scripts. I started re-writing them for 2.8 but then they’d get broken again.

Then I realized that writing these operators for objects and bmesh was not enough because there’s completely new operators for every different object types like curves, lights, armatures. Nothing’s unified. And behaviors are inconsistent from one object type to the next.

It became such a massive undertaking I just gave up.

Here’s some of the progress I made with a few places I wound up finding selection code to try and study:

And here’s another thread going over some of the hoops you have to jump through to get bmesh selections if you haven’t seen it already:


This sounds quite familiar to me. I wrote some pretty simple stuff for 2.80. It was broken in 2.83.

Separately, I wrote some other simple stuff for 2.83. It was broken in 2.9x.

This thread made me think that I needed to do the same as you–write my own generic, universal selection operator so I can at least approach something like a ls -sl level of function. But of course, if everything’s going to change massively on each point release, it’s wasted effort.


Yep, this is kind of where I got off the bus. I poured so many hours in just to have all the work blown to bits over and over it killed all my motivation to keep going.

I get that it’s a massive and badly needed overhaul for Blender and code changes are bound to break all kinds of things, but it just never felt like it was safe to try and move forward. And I was too unsatisfied with Blender’s selection design to keep pursuing it. I still like to follow development, though.

1 Like

There seems to be a lot of discussion for what could have been a fairly simple answer.

  • In Blender, selection is accessed by checking selected elements of a collection.
  • In edit-mode, you can access the edit-mesh directly (no need for mode-switching which is often inconvenient).

What is the problem with iterating over the entire mesh?
This is what a function would need to do to return the selected elements anyway.


This post from another thread sums it up well:

Is this no longer the case?

1 Like

If this is a generic approach, can you link or post code to execute it? I am not talking about code specific to vertices.

  • inefficient, possibly slow
  • requires knowing which mesh(es) are needed to iterate over
  • requires knowing which component type(s) are needed to iterate over
  • method incompatible with non-mesh component types of selection
  • takes several lines of code and logic–it should be no logic and one command
  • requires a specific UI context

Such a function is a basic feature of most 3D DCC applications. It’s also essential for generic workflows.

1 Like

It seems your expecting Blender’s Python API to behave in a way that it currently doesn’t.

Abstracting over element types, multiple meshes etc - and exposing the selection.

What your suggesting could be written as an API ontop of direct data access, although it probably needs to be integrated into operators for it to be useful.

So the answer to your question is - either access selection directly, or write your own utility functions.

While I’m interested in how the Python API could work differently, this probably requires changes at multiple levels.

I’d rather look at this in terms of problem/solution, showing code for current behavior and psudo-code for how it could work differently.

Although I don’t personally have a lot of time for this, it’s the kind of thing that could be prototyped in Python.

I’d describe it more as: I am looking for a basic utility function. If this doesn’t exist, okay–and I figure there must be an overriding reason for the lack, because it’s far more basic than many features which the applicaiton already possesses.

Do you mean via C? If not, how?

I could do this, but whatever I write will be crippled by my inexperience with the platform. Because it’s such a basic function, I will assume that others like @andyvandalsem will have already done this, and perhaps in such a way that point releases prioritise keeping it functioning–if Maya or Max or Houdini shipped without a functional concise selection reporting function, every 3D shop on the planet would grind to a halt. So having a platform newbie build this wouldn’t make much sense, if it’s to be included as a core function, as it’s likely to break between versions.

This sounds like a good way to approach it.

Some code is above–and this is specific to vertices on a specific mesh in a specific UI context.

How it might ideally function would be as a single encapsulating command, which doesn’t care about component or object type or UI context.

There are a tonne of ways to do it, the more featureful of which would get fairly involved.

In its most rudimentary form, it’d be bpy.utils.get_selection(), probably with filters for object types (meshes, components, transforms, etc), and for returning either strings (where appropriate) or objects.

1 Like

By looping over data and checking the select attribute.

When writing abstractions it often ends up not being as basic as you might think, you end up making assumptions about what the caller wants, which then need to be configurable to be used in different scenarios.

Script authors then need to become familier with the API abstraction and may run into situations it doesn’t support very well or figure how to extend the abstraction… what it’s limits are … etc.

  • What if the caller wants vertices even when in face-mode?
  • What if the caller wants only selected faces with valid UV coordinates.
  • How to access the object matrix of the vertices when multiple objects are in edit-mode?
  • How to handle multiple object instances of the same edit-mode data (return them multiple times or only once?)
  • How to handle mixing mesh selection modes vert/edge/face - return multiple elements when more than one is enabled?
  • How to access selected object (and not selected nodes, … files … UV’s etc, when other space-types are active).
  • How to differentiate between selected objects in local-view from selected objects in non-local 3D views?
  • Would the “selection” access have equivalent accessors for “visible”, “visible_editable”, “hidden” … even “user-defined” ?

… Of course all of this can be solved, everything can be made into an option - I assume other applications manage these kinds of issues, just noting that it’s not necessarily basic to write this kind of an API, unless it has limited defaults.

I rather see a full working MVP (a simple add-on for example) that does something useful, showing how poor the API is at performing the task. Otherwise it’s artificial and not necessarily so obvious what the issue is.

1 Like

First, thanks for the comprehensive reply.

Do all selectable scene data have a .select attribute? I don’t think they do. Is it always available for query (and returning correctly), or is it context-dependant? I don’t think it is.

Yes. I’ve written plenty of these over the years. The best approach is to make the simplest set of features possible, and build from there, where necessary. However, basic != simple. Basic in the sense, of, a minimal set of API utility functions in a 3D DCC application, in 2021 (or in the case of selection, 2005ish).

A selection query function should not fall to a script. That is inappropriate. It’s a core application method which should be part of the source, and required to function predictably across minor and major releases. In one popular software application, the same code (which consists of 6 characters) that queried selection in 1998 still functions now.

  • Mode should be irrelevant. This issue is part of why this post exists.
  • Filtering beyond reporting the selection list is an additional feature, outside scope.
  • Again, this issue is core to this thread. It shouldn’t matter. This is part of the problem. Whatever reports the selection list shouldn’t take mode into account.
  • Don’t handle modes. Whatever’s selected is reported. Selection mode is irrelevant. This type of function isn’t really for use with the UI anyway.
  • Report the list of selected data. Ignore the space type. If it’s in memory and selected (that is, if a user would see the selection while traversing the space type), report it. Adding filtering for space types might be of use as an additional feature, but again, outside scope.
  • These terms I am not familiar with, but I expect that you do not take this into account. Report the selection.
  • No, as these aren’t in the scope of ‘what’s selected’. If you have a list of what’s selected, your task of filtering for these additional attributes is already greatly simplified.

I can’t make an MVP because I am not a seasoned Blender developer. I’ve written some utilities for things I am doing, and an alarming proportion of them have been broken by point releases, and this is entirely in the 2.80+ era. This doesn’t inspire confidence that my work is valued enough to make sure that API functions persist across releases, and it points to this type of method necessarily being integrated into the core codebase, to protect it from this type of breakage.

The issue is far less how the API might be performing the task than how difficult it is for someone to harness the API to perform the task–I’d gladly give up some efficiency in this sphere just to be able to do it generically, which I currently can’t.


While no ill intent is meant, you’re basically saying that Blender should behave differently, without learning how Blender currently works. Further you’re not interested to provide a concrete example of the problems you hint at.

It seems like you put areas of the Python API in the too hard basket. I’d suggest you ask questions about tasks you think should be simple on stackexchange, collect some useful examples that help you understand the API, .

Some examples:

… once you have a few of these questions answered, development in these areas becomes less daunting. Of course this takes time to formulate good questions, YMMV.

I might be. Or I might be looking for functionality that a long career in CG has informed me should be present in a 3D application. Selection matters, especially in an application where so many operations are selection-dependant.

This thread is full of them. I clearly haven’t explained myself well enough. I haven’t been hinting but stating straight out:

  • (from what I can tell) there’s no generic ‘get selection’ method which functions independant of UI state or object/component type.

I am not sure how much more concrete I can be here. If this still isn’t clear enough, let me know.

Pointing out that something is missing or designed badly isn’t saying it’s “too hard”, it’s saying that it’s missing or designed badly. Those aren’t the same. Sure you can build a car with octagonal wheels, but why would you? I’ve tried to give the benefit of the doubt here, hoping that someone could explain why this is missing, but so far no one has. Maybe there’s a reason the wheels are octagonal; but I don’t know what that reason may be. I’d hate to think that the Blender python API is designed in a vacuum, ignoring common features, after all. I’m also not saying that there aren’t brilliant features as well. Saying that the wheels are octagonal doesn’t mean that the leather on the seats isn’t super supple.

When I went to stack exchange, they told me to come here. When I came here, they told me to go to stack exchange. Both places also told me to go to, where I was also told to come here and go to stack exchange. The circle is complete.

IMO stackexchange isn’t a forum (in fact, I was literally told this when I tried to treat it like one), and this is a topic for a development forum: Is there something like bpy.utilities.get_selection()? Why hasn’t it been created, if not? A developer in this very thread said they tried to implement their own solution, but it was broken by changes to the API. This function should be impervious to such changes.

Every developer I know who I’ve told about this over the past couple weeks can’t believe that this is the status quo. And I am inclined to agree: maybe there’s something I am not seeing, how could Blender possibly exist in its current feature filled form without being able to query selection?


You’ve said this multiple times now and I hate to be the bearer of bad news, but there isn’t. It’s natural for our brains to try and find rationality when presented with an irrational situation but there is none to be found here.

If I had to guess, once ‘good enough’ MVP API calls were added there was no impetus to improve the situation. Like, yeah sure you can usually get what you’re after, but it’s spread across 5 different places in a sub-optimal way that foists a large amount of work onto the python user. Blender’s python API to me feels like you’re given a tub full of small LEGO pieces or individual atoms and you’re expected to do all the heavy lifting and build everything yourself instead of providing improved data access and convenience functions.

As another example Blender has no function for ‘return object or component nearest to cursor’. While this could be a one-liner invoked in python with a few parameters (like depth or search radius around the cursor), instead you’re expected to build an entire unwieldy raycast function comprising dozens of lines of code yourself (see the template that ships with Blender) but you also can’t raycast onto objects that aren’t a mesh type! As far as I know the only way to get, for example, a light in object mode or a curve point in edit mode, is to invoke and pass the mouse coordinates, but this has its own problems: This actually alters the scene selection, rather than simply reporting back what’s under the cursor, and then there’s the limited functionality and the hard-coded selection accuracy of as mentioned by Andy.

Out of curiosity, in python my_selection = [v for v in bm.verts if] takes ~0.42 seconds on a triangulated 2.9 million vertex photogrammetry mesh (at least on my hardware). That’s nearly half a second just to find out what’s selected, without doing anything else in the script. Could the speed be materially different if Blender internally maintained its own list (analogous to bm.select_history but for all selected verts, not just some of them) that could be queried like my_selection = bm.selected_verts or is the python loop basically on par with how fast Blender could maintain such a list with C?


The hardcoded hitbox is a massive 28 x 28 pixels! You could click your screen and select an object on a computer 3 city blocks away!

Yes, this is exactly what I had to do. Alter the selection, compare it to the previous selection, then either restore selection to previous or update the selection based on comparison results. Because there’s no way to easily find out what’s near the cursor. And that wound up being a lot of code to do what I thought would be a pretty basic thing.

1 Like

2 million vert STL files have entered the chat…