How to Export Okta System Logs

How to Export Okta System Logs

SOC Prime Team
SOC Prime Team linkedin icon Follow

In the Okta Admin Console, Reports → System Log lets you search events and download the results. For JSON, use the System Log API: GET /api/v1/logs with since and until, following the next link until it runs out. A short script is below. Okta keeps System Log events for 90 days.

When identity is the perimeter, Okta’s System Log is the gate log. It records every sign-in, every MFA push, every factor reset and every admin role change. Prime Core has 58 detection rules for Okta data, mapped to 32 MITRE ATT&CK techniques. Among them: password spraying (T1110.003), MFA fatigue (T1621) and attackers tampering with MFA enrollment (T1556.006).

Get Started for Free

Before you start

Retention is 90 days. Anything older exists only where you’ve been streaming or forwarding Okta logs, such as a SIEM.

You need a token. An API token (Security → API → Tokens) inherits the permissions of the admin who created it. A read-only admin is enough for logs. For anything automated, an OAuth service app with the okta.logs.read scope is the cleaner choice. Either way, the token is a credential. Keep it out of shell history and revoke it when you’re done.

Rate limits apply. The logs endpoint has its own rate limit. Big windows are fine, just not instant.

Export with the System Log API

This Python script pages through a time window and writes one event per line. It needs requests (pip install requests):

import json, os, requests



org = "https://yourorg.okta.com"

headers = {"Authorization": f"SSWS {os.environ['OKTA_TOKEN']}", "Accept": "application/json"}

url = f"{org}/api/v1/logs"

params = {"since": "2026-10-19T00:00:00Z", "until": "2026-10-20T00:00:00Z", "limit": 1000}



with open("okta_1019.jsonl", "w") as out:

    while url:

        r = requests.get(url, headers=headers, params=params, timeout=60)

        r.raise_for_status()

        events = r.json()

        for e in events:

            out.write(json.dumps(e) + "\n")

        if not events:

            break

        url = r.links.get("next", {}).get("url")

        params = None  # the next link already carries the query

Always set until. Without it, Okta treats the request as a live poll and keeps handing back a next link. Your loop would run forever, waiting for new events.

To narrow it down, add a filter to params, for example “filter”: ‘eventType eq “user.session.start”‘. Or use “q”: “jane” for a keyword search.

What to look for

eventTypeWhy it matters
user.session.start with outcome.result: FAILUREFailed sign-ins; many users from one IP range means spraying
user.mfa.okta_verify.deny_pushUser rejected a push; a burst of these is MFA fatigue in progress
user.mfa.factor.deactivate, user.mfa.factor.reset_allFactors removed, often right after a helpdesk social-engineering call
user.account.privilege.grantAdmin role granted
policy.rule.update, policy.lifecycle.updateSign-on or MFA policy changed, possibly weakened
system.api_token.createA new API token, a quiet way to keep access

The fields that tell the story: actor.alternateId (who), client.ipAddress and client.geographicalContext (from where), outcome (what happened), and debugContext.debugData (the details).

Upload, sanitize and review in LogTotal

  1. Upload. Open logtotal.com and drop in the .jsonl file. [PROOF: upload screen, size limit]
  2. Sanitize. [PROOF: what gets masked: usernames and emails, IPs, device and session IDs]. Look it over before you continue.
  3. Review. [PROOF: what the results screen shows]

When it goes wrong

SymptomLikely causeFix
401Wrong or revoked token, or a missing SSWS  prefixCheck the header format; create a new token
403Token creator lacks rights to read logsUse a token from an admin with log access
429Rate limit hitWait for the time in X-Rate-Limit-Reset, then continue
The script never finishesNo until in the querySet until
Nothing older than 90 daysOkta retentionCheck your SIEM or log streaming destination

FAQ

Can’t I just use the Admin Console?

For a quick look at a short window, yes. For anything you want to analyze or keep, the API gives you complete JSON with every field.

Does this cover Auth0?

No. This guide is about Okta Workforce Identity. Auth0 has its own log format and API.

Join SOC Prime's Detection as Code platform to improve visibility into threats most relevant to your business. To help you get started and drive immediate value, book a meeting now with SOC Prime experts.