Threat Detection Basics
8 examples to get you started with GuardDuty threat detection via the SDK - 5 basic and 3 intermediate.
Search across all documentation pages
8 examples to get you started with GuardDuty threat detection via the SDK - 5 basic and 3 intermediate.
pip install boto3 (1.43.x, Python 3.10+) or Node.js npm install @aws-sdk/client-guardduty @aws-sdk/client-securityhub (AWS SDK v3, Node 18+).~/.aws/credentials, or an attached role).guardduty:CreateDetector, guardduty:ListFindings, guardduty:GetFindings, and securityhub:EnableSecurityHub permissions, or an admin who can grant them.One call turns on continuous threat detection - no agents, no log shipping to configure.
# --- Python (boto3) ---
import boto3
guardduty = boto3.client("guardduty", region_name="us-east-1")
detector = guardduty.create_detector(Enable=True)
detector_id = detector["DetectorId"]
print(detector_id)// --- TypeScript (AWS SDK v3) ---
import { GuardDutyClient, CreateDetectorCommand } from "@aws-sdk/client-guardduty";
const guardduty = new GuardDutyClient({ region: "us-east-1" });
const detector = await guardduty.send(new CreateDetectorCommand({ Enable: true }));
const detectorId = detector.DetectorId;
console.log(detectorId);CreateDetector only covers the region the client points at.CreateDetector again returns the existing detector's error, not a duplicate.Related: GuardDuty Detectors & Finding Types - data sources and severity in depth.
Confirm the detector is active before you build anything on top of it.
# --- Python (boto3) ---
import boto3
guardduty = boto3.client("guardduty", region_name="us-east-1")
status = guardduty.get_detector(DetectorId=detector_id)
print(status["Status"], status["FindingPublishingFrequency"])// --- TypeScript (AWS SDK v3) ---
import { GuardDutyClient, GetDetectorCommand } from "@aws-sdk/client-guardduty";
const guardduty = new GuardDutyClient({ region: "us-east-1" });
const status = await guardduty.send(new GetDetectorCommand({ DetectorId: detectorId }));
console.log(status.Status, status.FindingPublishingFrequency);Status should read ENABLED; anything else means findings are not being generated.FindingPublishingFrequency controls how often updated findings re-notify to CloudWatch Events/EventBridge (FIFTEEN_MINUTES, ONE_HOUR, SIX_HOURS).DetectorId - nearly every other GuardDuty call requires it.Findings are fetched in two steps - list IDs, then get details for the ones you want.
# --- Python (boto3) ---
import boto3
guardduty = boto3.client("guardduty", region_name="us-east-1")
resp = guardduty.list_findings(DetectorId=detector_id, MaxResults=25)
finding_ids = resp["FindingIds"]
print(len(finding_ids), "findings")// --- TypeScript (AWS SDK v3) ---
import { GuardDutyClient, ListFindingsCommand } from "@aws-sdk/client-guardduty";
const guardduty = new GuardDutyClient({ region: "us-east-1" });
const resp = await guardduty.send(new ListFindingsCommand({ DetectorId: detectorId, MaxResults: 25 }));
const findingIds = resp.FindingIds ?? [];
console.log(findingIds.length, "findings");ListFindings returns only IDs and supports a FindingCriteria filter (by severity, type, resource) plus pagination via NextToken.MaxResults caps at 50 per call; page with NextToken for more.GetFindings turns the IDs from step 3 into the actual finding records.
# --- Python (boto3) ---
import boto3
guardduty = boto3.client("guardduty", region_name="us-east-1")
details = guardduty.get_findings(DetectorId=detector_id, FindingIds=finding_ids[:10])
for f in details["Findings"]:
print(f["Type"], f["Severity"], f["Resource"].get("ResourceType"))// --- TypeScript (AWS SDK v3) ---
import { GuardDutyClient, GetFindingsCommand } from "@aws-sdk/client-guardduty";
const guardduty = new GuardDutyClient({ region: "us-east-1" });
const details = await guardduty.send(new GetFindingsCommand({
DetectorId: detectorId,
FindingIds: findingIds.slice(0, 10),
}));
for (const f of details.Findings ?? []) {
console.log(f.Type, f.Severity, f.Resource?.ResourceType);
}Type is a structured string like UnauthorizedAccess:EC2/SSHBruteForce - the namespace before the colon tells you the category, the rest the specific behavior.Severity is a float from 0 to 10 - roughly low (0-3.9), medium (4-6.9), high (7-10).GetFindings accepts up to 50 IDs per call; batch accordingly for large result sets.Most workflows only care about medium and above - filter server-side instead of fetching everything.
# --- Python (boto3) ---
import boto3
guardduty = boto3.client("guardduty", region_name="us-east-1")
resp = guardduty.list_findings(
DetectorId=detector_id,
FindingCriteria={"Criterion": {"severity": {"Gte": 4}}},
)
print(resp["FindingIds"])// --- TypeScript (AWS SDK v3) ---
import { GuardDutyClient, ListFindingsCommand } from "@aws-sdk/client-guardduty";
const guardduty = new GuardDutyClient({ region: "us-east-1" });
const resp = await guardduty.send(new ListFindingsCommand({
DetectorId: detectorId,
FindingCriteria: { Criterion: { severity: { Gte: 4 } } },
}));
console.log(resp.FindingIds);FindingCriteria supports filtering on severity, type, resource.resourceType, updatedAt, and more.SortCriteria to get the highest-severity findings first.Once you have investigated a finding and confirmed it is expected, suppress it without deleting the record.
# --- Python (boto3) ---
import boto3
guardduty = boto3.client("guardduty", region_name="us-east-1")
guardduty.archive_findings(DetectorId=detector_id, FindingIds=[finding_ids[0]])// --- TypeScript (AWS SDK v3) ---
import { GuardDutyClient, ArchiveFindingsCommand } from "@aws-sdk/client-guardduty";
const guardduty = new GuardDutyClient({ region: "us-east-1" });
await guardduty.send(new ArchiveFindingsCommand({ DetectorId: detectorId, FindingIds: [findingIds[0]] }));ListFindings view but remain retrievable by ID.CreateFilter with Action: "ARCHIVE") over one-off archiving when the same pattern recurs.Related: Threat Detection via SDK Best Practices - triage workflow and suppression hygiene.
Turn on an optional data source to widen coverage beyond the defaults.
# --- Python (boto3) ---
import boto3
guardduty = boto3.client("guardduty", region_name="us-east-1")
guardduty.update_detector(
DetectorId=detector_id,
DataSources={"S3Logs": {"Enable": True}},
)// --- TypeScript (AWS SDK v3) ---
import { GuardDutyClient, UpdateDetectorCommand } from "@aws-sdk/client-guardduty";
const guardduty = new GuardDutyClient({ region: "us-east-1" });
await guardduty.send(new UpdateDetectorCommand({
DetectorId: detectorId,
DataSources: { S3Logs: { Enable: true } },
}));DataSources also covers Kubernetes audit logs (EKS) and Malware Protection - each is billed separately based on volume scanned.GetDetector before assuming coverage.Add the aggregation and compliance layer on top of the findings you are already generating.
# --- Python (boto3) ---
import boto3
securityhub = boto3.client("securityhub", region_name="us-east-1")
securityhub.enable_security_hub(EnableDefaultStandards=True)// --- TypeScript (AWS SDK v3) ---
import { SecurityHubClient, EnableSecurityHubCommand } from "@aws-sdk/client-securityhub";
const securityhub = new SecurityHubClient({ region: "us-east-1" });
await securityhub.send(new EnableSecurityHubCommand({ EnableDefaultStandards: true }));EnableDefaultStandards: true subscribes you to AWS Foundational Security Best Practices automatically; set it false to choose standards explicitly.Related: GuardDuty & Security Hub Together - how the two services divide labor.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Reviewed by Chris St. John·Last updated Jul 25, 2026