Skip to main content
The Query API provides functions to create, execute, and manage queries programmatically. This reference covers the C API, which is the foundation for language bindings.

Creating Queries

ts_query_new

Create a query by specifying a string containing one or more patterns.

Parameters

const TSLanguage*
required
The language to create the query for. Must match the grammar used to parse the target syntax trees.
const char*
required
A string containing one or more query patterns written in the query syntax.
uint32_t
required
The length of the source string in bytes.
uint32_t*
Output parameter. If there’s an error, this will be set to the byte offset where the error occurred.
TSQueryError*
Output parameter. If there’s an error, this will be set to the error type.

Returns

A pointer to a TSQuery object, or NULL if there was an error.

Error Handling

If the query has syntax errors or references invalid node types or fields, the function still returns a TSQuery, but error_offset and error_type indicate the problem.
The TSQuery value is immutable and can be safely shared between threads.

Error Types

TSQueryError

Enumerates possible query errors:
0
No error occurred. The query is valid.
The query has a syntax error. Check the S-expression structure.
The query references a node type that doesn’t exist in the grammar.
The query references a field name that doesn’t exist in the grammar.
The query has an invalid capture name or usage.

Creating Query Cursors

ts_query_cursor_new

Create a cursor for executing queries.

Returns

A pointer to a new TSQueryCursor object.
Query cursors carry mutable state and should not be shared between threads. However, they can be reused for multiple query executions.

Executing Queries

ts_query_cursor_exec

Execute a query on a syntax node.

Parameters

TSQueryCursor*
required
The query cursor to use for execution.
const TSQuery*
required
The query to execute.
TSNode
required
The syntax tree node to search within. The query will match against this node and all its descendants.

Iterating Over Matches

Data Structures

The API provides structures for representing captures and matches:
Represents a single captured node.
  • node: The captured syntax tree node
  • index: The index of the capture in the query (corresponds to the order of @capture names)
Represents a complete pattern match.
  • id: Unique identifier for this match
  • pattern_index: Which pattern in the query matched (0-based)
  • capture_count: Number of captures in this match
  • captures: Array of captured nodes

ts_query_cursor_next_match

Retrieve the next match from the query cursor.

Parameters

TSQueryCursor*
required
The query cursor to retrieve matches from.
TSQueryMatch*
required
Output parameter. Will be populated with the next match’s data.

Returns

  • true if a match was found and match was populated
  • false if there are no more matches

Example Usage

Basic Query Execution

Error Handling

Reusing Query Cursors

Memory Management

  • Create with ts_query_new()
  • Use across multiple threads (read-only)
  • Delete with ts_query_delete() when done
  • Deletion is thread-safe if no queries are executing
  • Create with ts_query_cursor_new()
  • Use for one or more query executions (single thread)
  • Delete with ts_query_cursor_delete() when done
  • Do not share cursors between threads
  • TSQueryMatch is populated by reference
  • The captures array is valid until the next call to ts_query_cursor_next_match()
  • Copy data if you need to retain it longer

Advanced Features

Query Introspection

Queries expose information about their structure:

Query Predicates

Access predicates and directives programmatically:
Predicate evaluation is typically implemented in language bindings, not the C library. The C API exposes predicates in structured form for bindings to interpret.

Language Bindings

Most users interact with queries through language bindings:

Rust

tree-sitter crate provides idiomatic Rust API with predicate support

JavaScript

web-tree-sitter and Node bindings offer promise-based APIs

Python

tree-sitter package provides Pythonic interface with predicate evaluation
See language-specific documentation for:
  • Predicate implementation
  • Iterator patterns
  • Integration with language features

Performance Considerations

1

Share Queries

Create queries once and share them across threads. Query creation has overhead, especially for complex patterns.
2

Reuse Cursors

Within a thread, reuse query cursors for multiple executions. Cursor creation and deletion have some overhead.
3

Limit Query Scope

Execute queries on the smallest node that contains your target. Don’t query the entire tree if you only need a function body.
4

Optimize Patterns

More specific patterns (with field names and node types) are faster than generic ones. Use wildcards sparingly.

Next Steps

Query Syntax

Learn how to write query patterns

Predicates

Understand how to implement and use predicates

Parsers

Learn about parsing and syntax trees

Language Bindings

Explore Tree-sitter APIs in other languages