> ## Documentation Index
> Fetch the complete documentation index at: https://axiom.co/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# extract

> This page explains how to use the extract function in APL.

The `extract` function retrieves the first substring that matches a regular expression from a source string. Use this function when you need to pull out specific patterns from log messages, URLs, or any text field using regex capture groups.

## For users of other query languages

If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL.

<AccordionGroup>
  <Accordion title="Splunk SPL users">
    In Splunk SPL, you use `rex` with named or numbered groups. APL's `extract` is similar but uses a numbered capture group parameter.

    <CodeGroup>
      ```sql Splunk example theme={null}
      | rex field=message "user=(?<username>\w+)"
      ```

      ```kusto APL equivalent theme={null}
      ['sample-http-logs']
      | extend username = extract('user=([A-Za-z0-9_]+)', 1, uri)
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="ANSI SQL users">
    In ANSI SQL, regex extraction varies by database. APL's `extract` provides a consistent approach across all data.

    <CodeGroup>
      ```sql SQL example theme={null}
      SELECT REGEXP_SUBSTR(field, 'pattern', 1, 1, NULL, 1) AS extracted FROM logs;
      ```

      ```kusto APL equivalent theme={null}
      ['sample-http-logs']
      | extend extracted = extract('pattern', 1, field)
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

## Usage

### Syntax

```kusto theme={null}
extract(regex, captureGroup, text)
```

### Parameters

| Name         | Type   | Required | Description                                                                                             |
| ------------ | ------ | -------- | ------------------------------------------------------------------------------------------------------- |
| regex        | string | Yes      | A regular expression pattern with optional capture groups.                                              |
| captureGroup | int    | Yes      | The capture group to extract. Use 0 for the entire match, 1 for the first group, 2 for the second, etc. |
| text         | string | Yes      | The source string to search.                                                                            |

### Returns

Returns the substring matched by the specified capture group, or null if no match is found.

## Use case examples

<Tabs>
  <Tab title="Log analysis">
    Extract user IDs from HTTP request URIs to identify which users are accessing specific endpoints.

    **Query**

    ```kusto theme={null}
    ['sample-http-logs']
    | extend user_id = extract('/users/([0-9]+)', 1, uri)
    | where isnotempty(user_id)
    | summarize request_count = count() by user_id, method
    | sort by request_count desc
    | limit 10
    ```

    [Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B%27sample-http-logs%27%5D%20%7C%20extend%20user_id%20%3D%20extract\(%27%2Fusers%2F\(%5B0-9%5D%2B\)%27%2C%201%2C%20uri\)%20%7C%20where%20isnotempty\(user_id\)%20%7C%20summarize%20request_count%20%3D%20count\(\)%20by%20user_id%2C%20method%20%7C%20sort%20by%20request_count%20desc%20%7C%20limit%2010%22%7D)

    **Output**

    | user\_id | method | request\_count |
    | -------- | ------ | -------------- |
    | 12345    | GET    | 234            |
    | 67890    | POST   | 187            |
    | 11111    | GET    | 156            |
    | 22222    | PUT    | 98             |

    This query extracts numeric user IDs from URIs like '/users/12345' using a regex capture group, helping analyze per-user API usage patterns.
  </Tab>

  <Tab title="OpenTelemetry traces">
    Extract version numbers from service names to track which service versions are running.

    **Query**

    ```kusto theme={null}
    ['otel-demo-traces']
    | extend version = extract('v([0-9]+[.][0-9]+)', 1, ['service.name'])
    | where isnotempty(version)
    | summarize span_count = count() by ['service.name'], version
    | sort by span_count desc
    | limit 10
    ```

    [Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B%27otel-demo-traces%27%5D%20%7C%20extend%20version%20%3D%20extract\(%27v\(%5B0-9%5D%2B%5B.%5D%5B0-9%5D%2B\)%27%2C%201%2C%20%5B%27service.name%27%5D\)%20%7C%20where%20isnotempty\(version\)%20%7C%20summarize%20span_count%20%3D%20count\(\)%20by%20%5B%27service.name%27%5D%2C%20version%20%7C%20sort%20by%20span_count%20desc%20%7C%20limit%2010%22%7D)

    **Output**

    | service.name  | version | span\_count |
    | ------------- | ------- | ----------- |
    | frontend-v2.1 | 2.1     | 3456        |
    | checkout-v1.5 | 1.5     | 2341        |
    | cart-v3.0     | 3.0     | 1987        |

    This query extracts version numbers from service names, helping track which versions of services are generating traces.
  </Tab>

  <Tab title="Security logs">
    Extract IP addresses from URIs or request headers to identify the source of suspicious requests.

    **Query**

    ```kusto theme={null}
    ['sample-http-logs']
    | extend ip_address = extract('([0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3})', 1, uri)
    | where status == '403' or status == '401'
    | where isnotempty(ip_address)
    | summarize failed_attempts = count() by ip_address, status
    | sort by failed_attempts desc
    | limit 10
    ```

    [Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B%27sample-http-logs%27%5D%20%7C%20extend%20ip_address%20%3D%20extract\(%27\(%5B0-9%5D%7B1%2C3%7D%5B.%5D%5B0-9%5D%7B1%2C3%7D%5B.%5D%5B0-9%5D%7B1%2C3%7D%5B.%5D%5B0-9%5D%7B1%2C3%7D\)%27%2C%201%2C%20uri\)%20%7C%20where%20status%20%3D%3D%20%27403%27%20or%20status%20%3D%3D%20%27401%27%20%7C%20where%20isnotempty\(ip_address\)%20%7C%20summarize%20failed_attempts%20%3D%20count\(\)%20by%20ip_address%2C%20status%20%7C%20sort%20by%20failed_attempts%20desc%20%7C%20limit%2010%22%7D)

    **Output**

    | ip\_address   | status | failed\_attempts |
    | ------------- | ------ | ---------------- |
    | 192.168.1.100 | 401    | 45               |
    | 10.0.0.25     | 403    | 32               |
    | 172.16.0.50   | 401    | 28               |

    This query extracts IP addresses embedded in URIs from failed authentication requests, helping identify potential attackers or misconfigured systems.
  </Tab>
</Tabs>

## List of related functions

* [extract\_all](/apl/scalar-functions/string-functions/extract-all): Extracts all matches of a regex pattern. Use this when you need multiple matches instead of just the first one.
* [parse\_json](/apl/scalar-functions/string-functions/parse-json): Parses JSON strings into dynamic objects. Use this when working with structured JSON data rather than regex patterns.
* [split](/apl/scalar-functions/string-functions/split): Splits strings by a delimiter. Use this for simpler tokenization without regex complexity.
* [replace\_regex](/apl/scalar-functions/string-functions/replace-regex): Replaces regex matches with new text. Use this when you need to modify matched patterns rather than extract them.
