# Smap: a port scanner that reads Shodan instead of touching your targets

> It accepts Nmap syntax and produces Nmap output without sending a packet to the target, which is either exactly what you want or a decision that changes what your results mean.

**s0md3v/Smap** — a drop-in replacement for Nmap powered by shodan.io

- Repository: https://github.com/s0md3v/Smap
- Stars: 3,302 · Forks: 322
- Language: Go
- License: AGPL-3.0
- Published: 2026-10-08 · Updated: 2026-10-08 · Language: en
- Canonical page: https://hysenlabs.com/projects/s0md3v-smap

## The same arguments, a different source of truth

Smap is described as a drop-in replacement for Nmap, and the mechanism is simple to state: it is a passive port scanner built on shodan.io's free API. It does not probe the hosts you name. It asks Shodan what that index already knows about them and renders the answer in Nmap's shapes.

The argument compatibility is real but partial, and the README is specific about where the line falls. Options other than `-p`, `-h`, `-V`, `-o*`, `-iL`, `--concurrency` and `--append-output` are ignored in passive mode. That list is worth reading twice, because it means most of what makes Nmap Nmap, such as service detection scripts, timing templates and version probes, has no effect here.

So the drop-in claim holds at the level of invocation and output, not at the level of behaviour. A script that consumes Nmap's XML will keep working. A script that relied on Nmap's own probing to decide something will not be doing that any more, and nothing in the output format tells you so.

## Installing it

Three install paths are documented. Pre-built binaries are linked from the releases page, and the Go install path is a single line, which is the easiest route if you already have a Go toolchain:

```bash
go install -v github.com/s0md3v/smap/cmd/smap@latest
```

There are two AUR packages, `smap-git` which builds from source and `smap-bin` which packages the pre-built binary, and a Homebrew formula.

```bash
brew update
brew install smap
```

Note the case difference in the two GitHub paths. The repository is `s0md3v/Smap` with a capital S, while the Go install path and the module declaration in `go.mod` are lowercase `smap`. Go tooling is case sensitive about module paths, and the two forms coexist in the project's own documentation, which is a small trap if you are wiring this into a build script.

The `go.mod` file pins Go 1.25.0 and pulls in `publicsuffix-go` along with `golang.org/x/net` and `golang.org/x/text`. That dependency list is small for a tool that pretends to speak Nmap, which is consistent with a design that mostly formats other people's data.

## Targets, ports and the four ways to name a host

Target specification follows Nmap closely. One or more hosts can be given as arguments, or a newline-separated file can be passed with `-iL`. Four formats are documented for the file, and they cover most of what you would put in a scan list.

```bash
smap 127.0.0.1 127.0.0.2
smap -iL targets.txt
```

The default port set is roughly four thousand ports, taken from the list Shodan publishes, and `-p` narrows the display to specific ports or ranges.

```bash
smap -p21-30,80,443 -iL targets.txt
```

That default is the one number to internalize. A four-thousand-port passive scan and a four-thousand-port active scan are not comparable operations: the first asks about ports someone else already probed, and the second sends traffic to each one. Neither is wrong, but they answer different questions, and the passive one inherits whatever Shodan chose to look at rather than a decision you made.

Concurrency defaults to three workers, deliberately low, and can be raised with `--concurrency`. The stated reason is to avoid hitting Shodan too hard, which is a shared-infrastructure constraint rather than a performance one.

## Seven output formats and one that carries the extra data

Smap supports seven output formats selected with `-o*`, and a hyphen prints to the terminal.

```bash
smap example.com -oX output.xml
```

The formats are Nmap's XML, greppable and default formats, an `oA` mode that emits all three at once, `oP` for bare IP and port pairs, `oS` for a Smap-specific format, and `oJ` for JSON. Six of the seven exist so that existing Nmap tooling keeps working.

The seventh is the one with information in it. The README states plainly that Nmap does not scan or display vulnerabilities and tags, so that data is absent from Nmap's formats, and that you should use `-oS` to see it. Vulnerability detection and service fingerprinting are listed as features, and for passive mode they only surface in the custom format. A team that parses `-oX` into a dashboard is silently dropping the two data points that make passive scanning different from an active one.

## The --nmap path is the more interesting mode

The 1.0.0-beta release replaced an earlier `--active` flag with `--nmap`, and the change is worth understanding because it is where the project moved. Under `--nmap`, Smap collects the union of ports Shodan reports for the targets, substitutes that for the port range, and then hands the scan to a real Nmap, which handles the scanning and the output.

```bash
smap --nmap -Pn -sV --version-light 1.1.1.1
```

Except for `--nmap` and `--concurrency`, the supplied arguments go to Nmap. If you also specify `-p`, the Shodan candidates are limited to that range first. Host-only operations such as `-sL` and `-sn` pass through without passive discovery at all. If Shodan reports no candidate ports, Nmap is not run.

This is a genuinely good design, because it addresses the failure mode of both tools separately. Shodan is unreliable about what is not open, so it is used only to narrow the space. Nmap is reliable about what is open but slow across a wide range, so it only probes what survived the filter.

The README is also candid about the residual risk: because Shodan's data can be stale or incomplete, using it as a port filter can miss open ports. In this mode Smap makes active connections, so the no-contact property of passive mode no longer applies.

## What the README concedes

There is a Considerations section, and it is short and specific in a way that is easy to miss. Smap suits you if you want vulnerability detection, a very fast port scan, and no connections to the targets. It suits you if you are willing to accept no IPv6 support, results up to seven days old, and some rare unreliable software detection in passive mode.

Those four concessions line up with how the tool works rather than reading as hedging. Seven days is a property of a third-party index. No IPv6 is a property of that index too. Passive software detection is unreliable because it is inferred from banners observed by someone else's scan rather than probed.

The project also warns that previous versions in a workflow should be tested before updating, because 1.0.0-beta carries minor breaking changes, chiefly the `--active` to `--nmap` rename. GitHub reports 3,300 stars, 321 forks and a single open issue, and the last push was on 2026-08-15, the same day the beta tag was published. The one open issue is consistent with a project whose user base mostly uses the happy path.

## Conclusion

Smap makes sense for a specific and fairly common situation: you need to know which ports are open on a large set of hosts, and you are not authorized to or willing to send probe traffic to them. It gets there at a rate no active scanner can approach, because the work happened before you started. The trade is stated in the README itself: data can be up to seven days old, IPv6 is not supported, and passive software detection is unreliable on rare cases. Judge the tool on its own terms and the pairing with `--nmap` is the interesting part, since it takes Shodan's port candidates and then lets a real Nmap do the scanning. Start with `-p` on a single host to see how the output formats compare with what you are used to, and check whether your decisions depend on finding every open port before trusting a scan without `--nmap`.

## FAQ

### Does Smap send any traffic to the targets it scans?

Not in passive mode. Smap asks the Shodan API what it already knows about the hosts and formats the result, so no packets reach the targets. The exception is the --nmap flag, which passes the discovered ports to a real Nmap scan and does make active connections.

### Is Smap really a drop-in replacement for Nmap?

At the level of invocation and output, largely. It takes the same arguments and supports Nmap's XML, greppable and default output formats. At the level of behaviour, no: in passive mode every option except -p, -h, -V, -o*, -iL, --concurrency and --append-output is ignored.

### How old is the data Smap returns?

The README states results can be up to seven days old, because Smap reads from Shodan's existing index rather than scanning. It also notes that passive software detection is unreliable in rare cases and that IPv6 addresses cannot be scanned.

### Where do I see vulnerability findings in Smap output?

Not in Nmap's formats. The README states that because Nmap does not scan or display vulnerabilities and tags, that data is missing from the nmap formats, and that the -oS custom Smap format is where it appears.

## Sources

- [Issues](https://github.com/s0md3v/Smap/issues)
- [License: AGPL-3.0](https://github.com/s0md3v/Smap/blob/main/LICENSE)
- [README](https://github.com/s0md3v/Smap/blob/main/README.md)
- [Releases](https://github.com/s0md3v/Smap/releases)
- [s0md3v/Smap on GitHub](https://github.com/s0md3v/Smap)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/s0md3v-smap
