In the SDK, there are some altflags that can be used to distinguish whether a prototype for a given address has been guessed or specified by the user.
Specifically, you'd use the get_aflags function to get the 32-bit "aflags" for the address. After getting the flags, you'd then mask out your desired bit fields. The bitmask to select who guessed the prototype is AFL_TYPE_GUESSED(0xC2000000).
After you select the bits related to the AFL_TYPE_GUESSED field, you can then compare your result against one of the AFL_*_GUESSED flags, or specifically the AFL_USERTI flag to distinguish whether the prototype was determined explicitly by the user, ida, or the decompiler. The available additional flags are documented here.
If you're using IDAPython, you'll also probably want to use idaapi.as_uint32 to ensure you get an unsigned value since the AFL_TYPE_GUESSED bitmask has its high bit set.
So, the IDAPython code might look like:
def is_user_defined(ea): res = idaapi.get_aflags(ea) unsigned = idaapi.as_uint32(res) who = unsigned & idaapi.AFL_TYPE_GUESSED return who == idaapi.AFL_USERTI
It's probably worth noting that the "aflags" are stored in a netnode as an altval at the index NALT_AFLAGS(8) for the target address. If not using set_aflags, you can also use this to modify them.
Disclaimer: I'm the maintainer of the ida-minsc plugin that you can find on github at https://github.com/arizvisa/ida-minsc.
If you're using the ida-minsc plugin, the type information, names, and comments for all the things are indexed into the database and can be searched with tags. The specific tag name for the type information being manually applied to an address (or identifier for a structure or its members) is "__typeinfo__" and can be queried with database.select. Similarly, if you're trying to differentiate structures you created from ones automatically imported, you can use structure.select.
for ea, tags in database.select('__typeinfo__'): if function.has(ea): print(hex(ea), function.name(ea), function.type(ea), function.tag(ea)) continue
You can also use matchers (via the database.functions namespace) to select only the functions that are tagged, or you can gather them into a list if you want to filter them some more.
database.functions.list(tagged='__typeinfo__', like='sub_*') results = database.functions(tagged='__typeinfo__', decompiled=False) database.functions.list(ea=results, tagged=['__name__', 'synopsis'], problems=True)
To select functions that have not been prototyped by the user, you can do some basic set-arithemtic on the addresses returned. You can also use the "predicate" matcher with a custom test that selects functions not contained within the set.
tagged_results = set(database.functions(tagged='__typeinfo__', like='sub_*')) database.functions.list(address=set(database.functions()) - tagged_results) database.functions.list(predicate=lambda ea: ea not in results)
Disclaimer: Currently (as of 2025-05-08) the minsc plugin is limited to v8.4 due to the removal of the structure/enumeration api in 8.5 and 9.x.