Query Helpers
This page documents the committed source. Treat revision-sensitive RuneLite UI, packet, or in-game outcomes as pending live-client verification unless the page records direct evidence.
Query classes expose common collection-style helpers where the underlying type supports them:
withAnyAction,withoutActionnameContainsIgnoreCase,withTextContainsIgnoreCaseidIn(Collection<Integer>)withMappedName(String)on item, NPC, and tile object queriesexists,count,singlelimit,sortedwalkableon tile object and ground-item queriesgeTradeable
StringMatchers centralizes tag-stripping and case-insensitive matching.
For scene targets, compose eligibility filters before choosing a finalizer. walkable().nearestToPoint(anchor) selects the reachable object closest to a stable work-area anchor; nearestByPath() selects the shortest reachable target from the player. Do not use first() when the behavior promises nearest spatial selection because scene collection order is not a distance ranking.
ItemQuery.geTradeable() filters through ItemComposition.isGeTradeable(). Use it for Grand Exchange or market-facing filters. The older ItemQuery.tradeAble() remains for source compatibility and delegates to geTradeable(); it no longer uses RuneLite's broader ItemComposition.isTradeable() semantics.
ItemQuery.withMappedName(...), NPCQuery.withMappedName(...), and TileObjectQuery.withMappedName(...) resolve generated IDs through IdMapRegistry and then filter by ID. Item mapped-name lookups include RuneLite item variation groups for the current release. Add these helpers alongside existing exact runtime-name filters (withName(...)). See docs/id-maps.md for cache and import behavior.
ItemQuery name filters resolve the name from the widget first. If RuneLite does not populate a widget name, the query resolves the item ID through the project item-definition API before comparing. This keeps bank and inventory name filters usable when the live widget carries only item IDs.
All name predicates on ItemQuery, EquipmentItemQuery, and WidgetQuery (withName, nameContains, nameContainsNoCase, nameContainsIgnoreCase, matchesWildCardNoCase) route the widget side through Text.removeTags before comparing. Inventory and equipment widgets return styled names like <col=ff9040>Steel axe</col>; you can safely pass bare strings (nameContains("axe"), withName("Steel axe")) without manual stripping. The query parameter remains unstripped on nameContains family methods - keep call sites passing plain strings.
Examples:
Optional<NPC> banker = NPCs.search()
.withAnyAction("Bank", "Collect")
.nameContainsIgnoreCase("banker")
.nearestByPath();
List<Widget> firstFiveNotedItems = Bank.search()
.idIn(Set.of(561, 563, 565))
.limit(5)
.result();
Query Entry Points
Start from a static container and then chain a query object:
Inventory.search()->ItemQueryBank.search()->ItemQueryBankInventory.search()->ItemQueryEquipment.search()->EquipmentItemQueryDepositBox.search()->ItemQueryShop.search()->ItemQueryShopInventory.search()->ItemQueryGrandExchangeInventory.search()->ItemQueryTradeInventory.search(theirs)->ItemQueryNPCs.search()->NPCQueryPlayers.search()->PlayerQueryTileObjects.search()->TileObjectQueryTileItems.search()->TileItemQueryWidgets.search()->WidgetQueryProjectiles.search()->ProjectileQueryGraphicsObjects.search()->GraphicsObjectQueryItemContainers.search(int containerId)/ItemContainers.search(InventoryID)->ItemContainerQuery
BankItemWidget and EquipmentItemWidget are compatibility wrappers for bank and equipment item metadata. They do not implement RuneLite's Widget interface. Use getWidget() when a lower-level widget action needs the backing RuneLite widget.
Support matrix:
WidgetQuery: actions, text contains, item IDs, count/single/limit/sorted.ItemQuery: actions, names, mapped names, item IDs, GE tradeability, count/single/limit/sorted.EquipmentItemQuery: actions, names, equipment item IDs, count/single/limit/sorted.NPCQuery: actions, names, mapped names, IDs, count/single/limit/sorted.TileObjectQuery: actions, names, mapped names, IDs, walkable, count/single/limit/sorted.TileItemQuery: names, IDs, walkable, count/single/limit/sorted.PlayerQuery: names and collection helpers; this RuneLite API surface does not expose player action filtering.ProjectileQuery: IDs,targeting(Actor)/firedBy(Actor)actor filters, count/single/limit/sorted.GraphicsObjectQuery: IDs,active()(unfinished) andatLevel(int)plane filters, count/single/limit/sorted.ItemContainerQuery: item IDs, item-definition-backed names, quantity and container-index filters,totalQuantity(), count/single/limit/sorted.
ProjectileQuery and GraphicsObjectQuery take a fresh live snapshot on every search() call; they are not tick-cached. If you need the same view across several filters, keep reusing one query object (filters chain in place) rather than searching again mid-tick. See scene-queries.md.
Item Container Snapshots
ItemContainers.search(...) reads any item container - not only the widget-backed inventory, bank, and shop surfaces above - as an immutable snapshot. Each call copies the live container into ContainerItem value objects (getItemId(), getQuantity(), getIndex()); a snapshot never mutates afterwards, and empty or non-positive-ID slots are skipped. Name filters resolve through the project item-definition API. Like ProjectileQuery, a returned query mutates in place as filters chain, so take a fresh search(...) per independent assertion or pipeline stage.
List<ContainerItem> notedRunes = ItemContainers.search(InventoryID.BANK)
.nameContainsIgnoreCase("blood rune")
.result();
Query Pipeline Flow
The query pipeline converts a static facade scan of game objects/widgets/NPCs into a filtered stream of elements: