---
title: "Python"
description: ""
summary: ""
date: 2023-09-07T16:04:48+02:00
lastmod: 2023-09-07T16:04:48+02:00
draft: false
menu:
  docs:
    parent: ""
    identifier: "python-api"
weight: 530
toc: true
seo:
  title: "" # custom title (optional)
  description: "" # custom description (recommended)
  canonical: "" # custom canonical URL (optional)
  noindex: false # false (default) or true
---

Python is a popular language among YARA users. They use Python for all
kinds of automation tasks, and the YARA-X ecosystem wouldn't be complete
without the possibility of using it from Python programs.

YARA-X offers support for Python 3.9 or later, in Linux, MacOS and Windows.

## Installation

Installing the `yara-x` Python module couldn't be easier:

```shell
pip install yara-x
```

After the installation you can check if everything went fine by running
the following program:

```python
import yara_x

rules = yara_x.compile('''
  rule test { 
    strings: 
      $a = "foobar" 
    condition: 
      $a
  }''')

results = rules.scan(b"foobar")

assert results.matching_rules[0].identifier == "test"
assert results.matching_rules[0].patterns[0].identifier == "$a"
assert results.matching_rules[0].patterns[0].matches[0].offset == 0
assert results.matching_rules[0].patterns[0].matches[0].length == 6
```

If the program above runs without errors, everything is ready to start using
YARA-X from your Python programs.

## API overview

Using YARA-X from Python involves a two-step process: rule compilation and
scanning. During the rule compilation phase you transform YARA rules from text
into a compiled [Rules](#rules) object. This object is later used for scanning
data.

To compile rules, you can either use the [yara_x.compile(...)](#compile)
function or a [Compiler](#compiler) object. The former is simpler and sufficient
for simpler scenarios. For more complex use-cases involving the use of
namespaces and multiple rule sets, the latter method is necessary.

Once you have a [Rules](#rules) object, you can proceed in two ways: either use
the [Rules.scan(...)](#scanbytes) method, or create a [Scanner](#scanner).
Again, the former is the easiest way, but the later gives you more control over
the scanning process.

#### Examples

```python
# A very simple example
rules = yara_x.compile("rule test { condition: true }")
result = rules.scan(b"foo")
```

```python
# A more advanced example
compiler = yara_x.Compiler()
# Add more than one set of rules, each on a different namespace.
compiler.new_namespace("foo")
compiler.add_source("rule test { condition: true }")
compiler.new_namespace("bar")
compiler.add_source("rule test { condition: false }")
# Build the rules
rules = compiler.build()
# Pass the rules to a scanner, and set a scan timeout.
scanner = yara_x.Scanner(rules)
scanner.set_timeout(60)
scanner.max_matches_per_pattern(1000)
# Scan some data.
result = scanner.scan(b"foo")
```

## API reference

### compile(...)

Function that takes a string with one or more YARA rules and produces
a [Rules](#rules) object representing the rules in compiled form. This is
the simplest way for compiling YARA rules, for more advanced use-cases you
must use a [Compiler](#compiler).

Returns: [yara_x.Rules](#rules)

Raises: [yara_x.CompileError](#compileerror)

#### Example

```python
rules = yara_x.compile("rule test { condition: true }")
```

---------

### Compiler

Type that represents a YARA-X compiler. It takes one or more sets of YARA
rules in text form and compile them into a [Rules](#rules) object.

#### .\_\_init\_\_(relaxed_re_syntax=False)

Compiler constructor. The `relaxed_re_syntax` argument controls whether the
compiler should adopt a more relaxed syntax check for regular expressions,
allowing constructs that YARA-X doesn't accept by default.

YARA-X enforces stricter regular expression syntax compared to YARA. For
instance, YARA accepts invalid escape sequences and treats them as literal
characters (e.g., \R is interpreted as a literal 'R'). It also allows some
special characters to appear unescaped, inferring their meaning from the
context (e.g., `{` and `}` in `/foo{}bar/` are literal, but in `/foo{0,1}bar/`
they form the repetition operator `{0,1}`).

##### Example

```python
compiler = yara_x.Compiler(relaxed_re_syntax=True)
compiler.add_source("rule test { $a = /\Release/ condition: $a }")
```

#### .add_source(string, origin=None)

Adds some YARA source code to be compiled. Raises an exception if the source
code is not valid.

The optional `origin` parameter is a string that specifies the origin of the
source code. This is usually the path of the file containing the source code,
but it can be any arbitrary string conveying information about the source's
origin.

Raises: [yara_x.CompileError](#compileerror)

##### Example

```python
compiler = yara_x.Compiler()
compiler.add_source("rule test_1 { condition: true }")
compiler.add_source("rule test_2 { condition: false }", origin="test.yar")
rules = compiler.build()
```

#### .add_include_dir(path)

Adds a directory to the list of directories where the compiler should look for
included files. When an `include` statement is found, the compiler looks for the 
included file in the directories added with this function, in the order they were
added.

If this function is not called, the compiler will only look for included files in 
the current directory. Use [Compiler.enable_includes(...)](#enable_includesbool) for 
controlling whether include statements are allowed or not.

##### Example

```python
compiler = yara_x.Compiler()
compiler.add_include_dir("my_rules")
# The file "included.yar" is read from the "my_rules" directory.
compiler.add_source('include "included.yar" rule test_2 { condition: false }')
```

#### .define_global(identifier, value)

Defines a global variable and sets its initial value.

Global variables must be defined before
calling [Compiler.add_source(...)](#add_sourcestring-originnone) with some YARA
rule that uses the variable. The variable will retain its initial value when
the [Rules](#rules) are used for scanning data, however each scanner can change
the variable's value by
calling [Scanner.set_global(...)](#set_globalidentifier-value).

The type of `value` must be: `bool`, `str`, `bytes`, `int`, `float`, or `dict`.

When `value` is a `dict`, keys must be strings and valid YARA identifiers.
Values can be any supported type, including nested dicts and lists (for arrays).
Arrays must be homogeneous (all elements the same type). See
[External global variables]({{< ref "external_variables.md" >}}) for details on
using structs and arrays in rule conditions.

Raises: [TypeError](https://docs.python.org/3/library/exceptions.html#TypeError)
if the type of `value` is not one of the supported ones.

##### Example

```python
compiler = yara_x.Compiler()
compiler.define_global("my_int_var", 1)
compiler.add_source("rule test { condition: my_int_var == 1 }")
```

```python
compiler = yara_x.Compiler()
compiler.define_global("file_info", {
    "name": "test.exe",
    "size": 45056,
    "tags": ["packed", "unsigned"],
})
compiler.add_source('''
rule test {
    condition:
        file_info.name == "test.exe" and
        for any tag in file_info.tags : (
            tag == "packed"
        )
}
''')
```

#### .max_warnings(n)

{{< callout >}}
New in version 1.16.0
{{< /callout >}}

Sets the maximum number of warnings. The compiler will report only the first `n` warnings.

##### Example

```python
compiler = yara_x.Compiler()
compiler.max_warnings(1)
```

#### .enable_includes(bool)

Enables or disables the inclusion of files with the `include` directive. When includes
are disabled, any `include` directive encountered in the source code will be treated as
an error. By default, includes are enabled.

##### Example

```python
import yara_x

compiler = yara_x.Compiler()
compiler.enable_includes(False)  # Disable includes
```

#### .new_namespace(string)

Creates a new namespace. Any further call
to [Compiler.add_source(...)](#add_sourcestring-originnone) will put the new
rules under the new namespace, isolating them from previously added rules.

##### Example

```python
compiler = yara_x.Compiler()
compiler.new_namespace("foo")
# This "test" rule is under the "foo" namespace
compiler.add_source("rule test { condition: true }")
compiler.new_namespace("bar")
# This "test" rule is under the "bar" namespace. The rules 
# don't collide even if they are both named "test".
compiler.add_source("rule test { condition: false }")
rules = compiler.build()
```

#### .allowed_metadata(identifier, value_type, required=False, error=False, regexp=None)

Defines expectations for a specific metadata field.

When rules are compiled, the compiler will check if the metadata fields match the specified expectations. If not, it will trigger a warning (or an error if `error` is `True`).

- `identifier`: The metadata name (e.g., `"author"`).
- `value_type`: The expected type, which must be one of the `yara_x.MetaType` constants:
  - `MetaType.STRING`
  - `MetaType.INTEGER`
  - `MetaType.FLOAT`
  - `MetaType.BOOL`
  - `MetaType.SHA256`
  - `MetaType.SHA1`
  - `MetaType.MD5`
  - `MetaType.HASH`
- `required`: If `True`, the metadata field must be present in every rule. Defaults to `False`.
- `error`: If `True`, failure to meet the expectation triggers an error instead of a warning. Defaults to `False`.
- `regexp`: An optional regular expression that the metadata value must match. Only applicable if `value_type` is `MetaType.STRING`.

##### Example

```python
compiler = yara_x.Compiler()
compiler.allowed_metadata("author", yara_x.MetaType.STRING, required=True)
compiler.allowed_metadata("version", yara_x.MetaType.STRING, regexp=r"^\d+\.\d+$")
```

#### .allowed_rule_name(regexp, error=False)

Specifies a regular expression that the compiler will enforce upon each rule name.
Any rule with a name that does not match this regular expression will trigger a warning.
If `error` is `True`, it will trigger an error instead of a warning.

##### Example

```python
compiler = yara_x.Compiler()
compiler.allowed_rule_name("^test_")
```

#### .allowed_tags(tags, error=False)

Sets a list of allowed tags. Any rule with a tag not present in this list will trigger a warning.
If `error` is `True`, it will trigger an error instead of a warning.

##### Example

```python
compiler = yara_x.Compiler()
compiler.allowed_tags(["foo", "bar"])
```

#### .allowed_tags_regex(regexp, error=False)

Specifies a regular expression that the compiler will enforce upon each tag.
Any rule with a tag that does not match this regular expression will trigger a warning.
If `error` is `True`, it will trigger an error instead of a warning.

##### Example

```python
compiler = yara_x.Compiler()
compiler.allowed_tags_regex("^[a-z]+$")
```

#### .errors()

Returns the errors found during the compilation, across all calls to
[Compiler.add_source(...)](#add_sourcestring-originnone). The result is an
array of dictionaries, where each dictionary represents an error. This
is an example:

```json
 [
  {
    "type": "UnknownIdentifier",
    "code": "E009",
    "title": "unknown identifier `foo`",
    "labels": [
      {
        "level": "error",
        "code_origin": null,
        "span": {
          "start": 25,
          "end": 28
        },
        "text": "this identifier has not been declared"
      }
    ],
    "text": "... <full report here> ..."
  }
]
```

#### .warnings()

Returns the warnings found during the compilation, across all calls to
[Compiler.add_source(...)](#add_sourcestring-originnone). The result is an
array of dictionaries, where each dictionary represents a warning. This is
an example:

```json
[
  {
    "type": "SlowPattern",
    "code": "slow_pattern",
    "title": "slow pattern",
    "labels": [
      {
        "level": "warning",
        "code_origin": null,
        "span": {
          "start": 25,
          "end": 28
        },
        "text": "this pattern may slow down the scan"
      }
    ],
    "text": "... <full report here> ..."
  }
]
```

#### .build()

Produces a compiled [Rules](#rules) object that contains all the rules
previously added to the compiler
with [Compiler.add_source(...)](#add_sourcestring-originnone). Once this method
is called the Compiler is reset to its original state, as if it was a newly
created compiler.

### Rules

Type that represents a set of compiled rules. The compiled rules can be used for
scanning data by calling the [Rules.scan(...)](#scanbytes) method or passing
the [`Rules`](#rules) object to a [Scanner](#scanner).

#### .scan(bytes)

Scans data with the compiled rules. This is the simplest way of using the
compiled rules for scanning data. For more advanced use-cases you can use
a [Scanner](#scanner).

Returns: [yara_x.ScanResults](#scanresults)

Raises: [yara_x.ScanError](#scanerror), [yara_x.TimeoutError](#timeouterror)

#### .scan_with_options(bytes, options)

Like [Rules.scan(...)](#scanbytes), but allows to specify additional scan options.

Returns: [yara_x.ScanResults](#scanresults)

Raises: [yara_x.ScanError](#scanerror), [yara_x.TimeoutError](#timeouterror)

#### .imports()

An array with the names of the modules imported by the rules.

#### .serialize_into(file)

Serializes the rules into a file-like object.

##### Example

```python
rules = yara_x.compile("rule test { condition: true }")
f = io.BytesIO()
rules.serialize_into(f)
f.seek(0)
rules = yara_x.Rules.deserialize_from(f)
```

#### .deserialize_from(file)

Deserializes rules from a file-like object.

##### Example

```python
rules = yara_x.compile("rule test { condition: true }")
f = io.BytesIO()
rules.serialize_into(f)
f.seek(0)
rules = yara_x.Rules.deserialize_from(f)
```

---------

### Scanner

Type that represents a YARA-X scanner. When creating the Scanner you must
provide a [Rules](#rules) object containing the rules that will be used
during the scan operation. The same [Rules](#rules)  can be used by multiple
scanner simultaneously.

##### Example

```python
rules = yara_x.compile("rule test { condition: true }")
scanner = yara_x.Scanner(rules)
```

#### .scan(bytes)

Scans in-memory data.

Returns: [yara_x.ScanResults](#scanresults)

Raises: [yara_x.ScanError](#scanerror), [yara_x.TimeoutError](#timeouterror)

##### Example

```python
rules = yara_x.compile('rule foo { strings: $foo = "foo" condition: $foo }')
scanner = yara_x.Scanner(rules)
scanner.scan(b"foobar")
```

#### .scan_with_options(bytes, options)

Like [Scanner.scan(...)](#scanbytes-1), but allows to specify additional scan options.

Returns: [yara_x.ScanResults](#scanresults)

Raises: [yara_x.ScanError](#scanerror), [yara_x.TimeoutError](#timeouterror)

##### Example

```python
rules = yara_x.compile('rule foo { strings: $foo = "foo" condition: $foo }')
scanner = yara_x.Scanner(rules)
options = yara_x.ScanOptions()
options.set_module_metadata("cuckoo", b'{"foo": "bar"}')
scanner.scan_with_options(b"foobar", options)
```

#### .scan_file(path)

Scans a file given its path.

Returns: [yara_x.ScanResults](#scanresults)

Raises: [yara_x.ScanError](#scanerror), [yara_x.TimeoutError](#timeouterror)

##### Example

```python
rules = yara_x.compile('rule foo { strings: $foo = "foo" condition: $foo }')
scanner = yara_x.Scanner(rules)
scanner.scan_file("foo.bin")
```

#### .scan_file_with_options(path, options)

Like [Scanner.scan_file(...)](#scan_filepath), but allows to specify additional scan options.

Returns: [yara_x.ScanResults](#scanresults)

Raises: [yara_x.ScanError](#scanerror), [yara_x.TimeoutError](#timeouterror)

##### Example

```python
rules = yara_x.compile('rule foo { strings: $foo = "foo" condition: $foo }')
scanner = yara_x.Scanner(rules)
options = yara_x.ScanOptions()
options.set_module_metadata("cuckoo", b'{"foo": "bar"}')
scanner.scan_file_with_options("foo.bin", options)
```

#### .set_global(identifier, value)

Sets the value of a global variable. The variable must has been previously
defined during the compilation, for example by calling
[Compiler.define_global(...)](#define_globalidentifier-value), and the type it
has
during the definition must match the type of the new value. The variable will
retain the new value in subsequent scans, unless this function is called again
for setting a new value.

Raises: [TypeError](https://docs.python.org/3/library/exceptions.html#TypeError)
if the type of `value` is not one of the supported ones.

#### .set_timeout(seconds)

Sets a timeout for each scan. Scans will abort after the specified `seconds`.

#### .fast_scan(bool)

Enables or disables fast scan mode.

In fast scan mode, the scanner avoids tracking matches for patterns when it is
not necessary (e.g. when a rule condition only performs a simple boolean check
`$a`).

Note that using fast scan mode implies that not all matches will be reported. 
For instance, when iterating matches, you won't get all occurrences of the 
pattern in the file, only the first one.

---------

### ScanOptions

Type that represents a set of optional information for the scan operation.

#### .__init__()

Creates a new [`ScanOptions`](#scanoptions) object.

##### Example

```python
options = yara_x.ScanOptions()
```

#### .set_module_metadata(module, metadata)

Sets the data associated with a YARA module.

When scanning a file, YARA modules may require additional data that is
not present in the file itself. For instance, the `cuckoo` module may
need a report from Cuckoo sandbox with information about the file being
scanned.

This function is used for providing that data to the modules. The data
is specific to the module, and each module expects a different data
structure. The data is passed as raw bytes that the module is responsible
to decode accordingly.

##### Example

```python
rules = yara_x.compile('import "cuckoo"')
options = yara_x.ScanOptions()
options.set_module_metadata("cuckoo", module_metadata)
rules.scan_with_options(data, options)
```

---------

### ScanResults

Type that represents the results of a scan operation.

#### .matching_rules

Array of [Rule](#rule) objects with every rule that matched during the scan.

#### .module_outputs

A dictionary containing the information extracted by all YARA-X modules from
the file. Keys in the dictionary are module names (i.e: "pe", "elf", "dotnet",
etc), and values are dictionaries with the information produced by each module.

---------

### Rule

Type that represents an individual YARA rule.

#### .identifier

A `str` with the rule's identifier.

#### .namespace

A `str` with the rule's namespace.

#### .patterns

A tuple of [Pattern](#pattern) with every pattern defined by the rule, matching
or not. Each pattern contains information about the matches that were found
during the scan, if any.

#### .metadata

A tuple of pairs `(identifier, value)` with the metadata associated to the
rule.

### Pattern

Type that represents a pattern in a [Rule](#rule). Contains information about
the pattern, including its identifier and the matches found for that pattern,
if any.

#### .identifier

A `str` with the pattern's identifier (i.e: `$a`, `$foo`, etc).

#### .matches

A tuple of [Match](#match) objects that contain information about the matches
found for this pattern.

---------

### Match

Type that represents a match found for a [Pattern](#pattern).

#### .offset

The file offset where the match occurred.

#### .length

The length of the match.

#### .xor_key

If the pattern used the [xor]({{< ref "text_patterns.md" >}}#xor-modifier)
modifier, this contains the XOR key (it may be 0). If not, this is `None`.

---------

### Module

Type that represents a YARA module. Modules are extensions that can provide additional functionality and capabilities
to YARA rules. This class allows leveraging modules for parsing some file formats independently of any YARA rule.

##### Example

```python
pe_info = yara_x.Module('pe').invoke(data)
```

In the example above, the `invoke` function is called with some binary data read from a PE file. The YARA `pe` module
parses the data and returns a dictionary with all the metadata extracted from the PE file.

#### .invoke()

Invokes the functionality of the module.

---------

### CompileError

Exception raised when compilation fails.

##### Example

```python
try:
  rules = yara_x.compile('invalid rule')
except yara_x.CompileError as err:
  print(err)
```

---------

### ScanError

Exception raised when scanning fails.

```python
try:
  scan_results = scanner.scan(b"foobar")
except yara_x.ScanError as err:
  print(err)
```

---------

### TimeoutError

Exception raised when a timeout occurs while scanning.

```python
try:
  scan_results = scanner.scan(b"foobar")
except yara_x.TimeoutError as err:
  print("A timeout occurred")
```