Introduction
Today Fox-IT is releasing its full Cobalt Strike Beacon Corpus, containing 56,843 raw beacons and their parsed configurations, from 192,979 sightings collected from 30,604 unique IP addresses running a Team Server (the Cobalt Strike command-and-control server that beacons connect back to) between 4 July 2018 and 29 September 2026, over eight years of beacon data. The corpus is available on Hugging Face:
In March 2022 we published Mining Data from Cobalt Strike Beacons. That post covered 128,340 beacon sightings collected from July 2018 to February 2022, and it introduced our Python project dissect.cobaltstrike for parsing them.
Since then, public scanning for Team Servers has become routine, and Cobalt Strike has shipped versions 4.6 through 4.13. Researchers have regularly asked us for an updated dataset. And here it is, a large, consistent, long-running dataset for the security community to build on. We're including the raw beacons, not just our parsed output, so anyone can reproduce our results or improve on them.
We also see publishing this corpus as an act of preservation. C2 infrastructure is short-lived, as the median Team Server is reachable for just 14 days, and the beacons it serves vanish with it. Eight years of collection captures things that can no longer be observed today, like the waves of cracked 4.0 builds or the adoption of leaked versions. By publishing the raw beacons alongside the parsed data, we keep that record available for anyone to study, long after the servers themselves are gone.
What's in the corpus
The corpus is published on Hugging Face as two Parquet files:
|
File |
Size |
Rows |
Contents |
|---|---|---|---|
|
beacons.parquet |
52MB |
19082 |
Every sighting of a beacon, with collection metadata, network context and the parsed beacon configuration. |
|
payloads.parquet |
9.7GB |
56843 |
The raw beacon payloads, wrapped in CaRT as an extra safety layer so the samples are neutered until you deliberately unpack them. |
All beacons were downloaded directly from internet-facing Team Servers, mostly on TCP ports 80 and 443 (HTTP and HTTPS) and UDP port 53 (DNS), with a small number on other ports. We deliberately didn't include samples from other sources such as VirusTotal, so the corpus reflects the Cobalt Strike landscape as it is visible on the internet.
How we collected it
The method matches the 2022 post. We fingerprint likely Team Servers on the internet, then request a beacon payload from each one using a URI that passes Cobalt Strike's checksum8 check. Every beacon that comes back is parsed with dissect.cobaltstrike, and decodes the configuration block.
- Discovery: candidate hosts from our own internet-wide scanning. As in 2022, we're keeping our fingerprints private so they stay effective; writing your own is left as an exercise for the reader.
- Download: x86 beacons over HTTP and HTTPS on ports 80, 443, 8080, and DNS.
- DNS: For DNS listeners we're not publishing that fingerprint either, but it's not rocket science. The beacon is fetched as a series of TXT record lookups sent over UDP port 53 directly to the Team Server's DNS listener.
- Parse: Use dissect.cobaltstrike to parse the beacon and export the configuration
- Enrich: TLS certificate data captured at collection time (some were sadly not logged) and GeoIP/ASN via historical GeoIP databases.
Note that there might be some gaps in the collection due to automation errors.
Getting started
Most research only needs the beacons.parquet dataset. The payloads.parquet dataset containing raw beacon payloads is only required if you want to re-parse them or look into the ones that failed parsing.
In 2022 we wrote every query and chart in our notebook by hand with pandas. This time an AI assistant did most of that work. We described what we wanted, and it wrote the DuckDB SQL and the charts in the next sections, which we then checked and tweaked. We recommend the same approach. Point an assistant at the schema and ask your question, but verify the output. Early on, ours silently returned empty results because it guessed the wrong JSON paths.
An example of using DuckDB to query the dataset on Hugging Face directly:


You can also use our Jupyter notebook in the Hugging Face repository as a starting point. It has every query and chart from the sections below, so you can rerun them or adapt them to your own research questions.
A first look at the data
Here are a few quick results to show what the corpus can answer. They're a starting point, not a full analysis. As with our 2022 post, we invite researchers to explore the data; see also "Research ideas" at the end.
Old versions never die

Each release takes over from the last, but old versions linger: 4.0 dominated 2020, 4.3–4.4 drove the 2021 peak of about 3,000 beacons a month, and 4.9 has led since 2024, while 4.10+ remains a small share. Volume has since fallen below 200 a month, partly because fewer servers stage their beacon, which bring us to the next graph.
No beacon for you
![]()
Our collection relies on beacon staging: a Team Server can serve its beacon as a downloadable payload to anyone who requests the right URI or DNS record. Operators can turn this off (the host_stage option in the Malleable C2 profile), and disabling it is common OPSEC advice.
To measure how much this affects our beacon collection, we counted two numbers per month:
- the unique IPs running a Team Server, confirmed by our high-confidence HTTP fingerprint (the fingerprint results are not part of the corpus)
- the unique IPs that handed out a beacon over HTTP(S).
These are monthly totals, not a server-by-server match. On average, the IPs that handed out a beacon were only about 32% of those we fingerprinted, and that share has drifted down from around 40% in 2023 to 20–25% in 2026.
In other words, because not every server hands out a beacon, the corpus shows only part of the Cobalt Strike landscape, and that part is getting smaller. Disabled beaco staging is the most likely reason, but not the only one. Servers can go offline between fingerprinting and download or block our scanners, and our fingerprint doesn't catch every Team Server.
The dashed sections mark months when beacon collection wasn't running, because of an automation error that went unnoticed for a while.
The short life of a Cobalt Strike Team Server

The median Team Server was reachable for 14 days. 35% were seen on a single day only, just 14% were still serving a beacon after three months, and only 2% after a year.
We identify a Team Server by its public key and C2 domains from the beacon configuration (or its IP address when the configuration contains no domains), so a server that moves to a new IP is still counted once. This allows us to measure how long a Team Server typically stays online. Identifying servers by public key alone or by ip:port gives almost the same result: a median lifetime of 14–15 days. These are first-to-last-sighting spans: a server may have been online before our first and after our last sighting, and servers still active in the last 30 days are left out.
It’s always DNS

Most public scanning focuses only on HTTP(S) beacons, but we've also collected DNS beacons since 2020 (apart from the months when our automation broke). DNS beacons have declined much less steeply than HTTP(S) ones, perhaps because they get far less attention in public research and OPSEC advice, so fewer operators think to lock them down. After a peak in 2022, they have hovered between roughly 80 and 140 a month since 2024, with a median of 120 over the whole period.
Parse me if you can
The corpus also includes 128 unique beacons (0.23%) that we downloaded but couldn't parse.
Note that the corpus doesn't contain HTML pages or other responses that were unlikely to be a beacon. We excluded those before publishing.
At first glance, most are beacons with custom modifications that dissect.cobaltstrike can't parse yet. Some payloads from the early years aren't Cobalt Strike at all, but Metasploit Meterpreter payloads served by servers that looked like Team Servers. We've deliberately left them in for researchers to analyze. You can find all unparsed beacons with config_json IS NULL.
The unparsed count used to be higher. Some operators customize their beacons, for example by shuffling the order of the configuration settings or changing their type values, which broke our parser (and probably most others). The corpus helped us find these cases, so we made dissect.cobaltstrike's config scanning independent of layout and added many other features and fixes along the way.
Limitations and responsible use
The corpus shows the general Cobalt Strike landscape on the public facing internet. It doesn't cover the whole Cobalt Strike ecosystem. Keep these biases in mind before drawing conclusions:
- Coverage: Only Team Servers that serve beacons and match our fingerprints are included. Limited to certain ports. Servers with staging turned off, strict profiles or redirectors are under-represented. The same applies for domain fronted beacons, unless they showed up because it was exposed directly on the internet or was found via specific hunting.
- Not all malicious: Legitimate red teams show up too. Don't treat an IP or watermark as malicious on the corpus alone.
- Stale data: IPs and domains get reassigned. A record tells you what a host served on the collection date, not what it serves now.
- Gaps: There might be some small gaps in the collection due to automation outages or errors.
- Raw beacons: Each beacon is wrapped in CaRT, which encodes the file so antivirus doesn't flag or quarantine it. This lets us release the full set, which is too large to upload to VirusTotal or MalwareBazaar, while keeping the samples inert until someone unpacks them on purpose. Beacons are still live malware stagers and may contain working C2 addresses, so handle them the way you would any malware sample.
- What's excluded: The corpus does not contain anything that would help someone run or crack Cobalt Strike.
Research ideas
Some other research questions that could be answered using the corpus:
- Clustering: Group operators by config features (watermark, SPAWNTO/PROCINJ hash, C2 profile, certificate, sleep/jitter, specific beacon modifications)
- Classification: Separate red team from criminal infrastructure. Build and publish labelled subsets.
- Profile drift: Track how popular public Malleable C2 profiles are adopted and modified over time.
- Infrastructure: Top hosting providers that are hosting a Cobalt Strike team server.
- Certificates: Pivot on x509 reuse across servers and time or find how many are running the default Cobalt Strike keystore certificate.
- Benchmarks: Use the corpus as a shared test set for config extractors and ML models.
- Parser failures: 128 beacons can't be parsed by dissect.cobaltstrike. Find out why: new versions, custom obfuscation, corrupted downloads or something else.
If you publish something cool built on the corpus, share it in the Discussions tab of the Hugging Face repository so others can find it.
Over to you
In 2022 we called the dataset "only the tip of the iceberg", and this release gives you much more of it. Download it, break it and tell us what you find.
- Corpus: https://huggingface.co/datasets/fox-srt/cobaltstrike-beacon-corpus
- Tooling: dissect.cobaltstrike on GitHub, pip install dissect.cobaltstrike
- Previous post: Mining Data from Cobalt Strike Beacons (March 2022)