geowifi queries several public Wi-Fi databases at once and merges their answers
Search WiFi geolocation data by BSSID and SSID on different public databases.
At a glance
- What is it?
- geowifi is a small Python tool that takes a BSSID or an SSID and asks several public geolocation databases for an answer, then returns the results as JSON or on a map. It needs API keys for some of those services, it depends on a handful of third party APIs staying online, and its licence status is not stated in the repository.
- Who is it for?
- geowifi fits an OSINT investigator who already has a BSSID or SSID from a capture and wants to know where that access point has been seen, without writing eight API clients. It is the wrong tool if you need to collect access points yourself, since it looks things up rather than scanning.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 44 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One identifier, several public answers
geowifi searches Wi-Fi geolocation data by BSSID and SSID on different public databases. That is the whole product, and the interesting part is the second half of the sentence.
The databases are listed in a table in the README: Wigle, Apple, Google, Milnikov, WifiDB, Combain, Freifunk Carte, and OpenWifi, which is marked as discontinued. Each of these is a separate service with its own API, its own coverage and its own idea of what a BSSID row contains, and the tool's value is that you query them all in one command instead of writing a client for each.
The audience is written into the topics: geolocation, OSINT and wifi. The README's credits section names the project's lineage, saying it uses some of the research and code used at iSniff-GPS, and thanks Micah Hoffman for answers to questions and kennbro for feedback. That is a good pointer to the source of the method: iSniff-GPS is the project that pairs a capture with a location lookup, and geowifi is the lookup half of that idea, packaged on its own.
The difference in approach between the two is worth keeping in mind. A capture and locate workflow produces the BSSID and SSID first and then asks where they have been seen, and geowifi starts from the second step, taking the identifier as its input. That is a smaller and more reusable tool, and it is also a tool that does nothing until you have an identifier from somewhere else.
The output is a per-database answer sheet, including the failures
The result format is the most honest part of the design. The JSON output example in the README is a list of objects, one per module, and each object is either a result or an error.
[
{
"module": "google",
"bssid": "C8:XX:XX:XX:5E:45",
"latitude": 33.571844,
"longitude": -1XX.XXXXX97
}, The module key tells you which service answered, and the example shows the full set that a single query can produce: google, combain, mylnikov, vendor_check, apple, wigle and wifidb. The vendor_check module is not a geolocation service at all, it returns the vendor string, and in the example it identifies the access point as Cisco-Linksys, LLC.
The error entries are as informative as the successes. Combain comes back with an error reading Not enough witooth, which is a distinct answer from a service that simply has no record, and Milnikov returns Object was not found. A tool that silently dropped the databases which failed would tell you less, because you would not know whether a missing coordinate means the access point is unknown to that service or that the service was unreachable.
In the successful case the payload carries the bssid, the latitude and the longitude, and for Wigle and WifiDB also the ssid. That difference matters too. Wigle and WifiDB return a name along with the position, which tells you which network was seen at that spot, while the other services return coordinates only.
Three API keys and one configuration file
The tool has a configuration file in the gw_utils folder called config.yaml, and the README explains each parameter and where to get the value.
The first is wigle_auth. Using the Wigle service requires an API, and the config value is the Encoded for use data provided on the Wigle account page. The second is google_api, for the Google Geolocation Services API key, and the README notes that Google provides $200 of free monthly usage. The third is combain_api, for the Combain API, and Combain provides a free trial and paid plans.
So three of the eight databases need credentials and five do not, which shapes what a first run looks like. A user without any keys can still query the open services, but the results will be thinner than the example output in the README, where the well known services all answered.
The fourth parameter is no-ssl-verify, an option to enable or disable the SSL verification process on requests. The README documents it as a switch without saying when to use it, and it deserves a note. Disabling certificate verification removes the protection that stops an intercepted connection from serving a modified response, and since this tool's whole job is to trust what remote services say about where an access point is, that switch is best left off outside a debugging session.
The Docker image carries the same configuration, since the compose of the tool is the same in both cases: the config file is the only thing you have to prepare before a query.
Two ways to install, one way to run it
The installation section gives a git route and a zip route, and then a local Python setup and a Docker setup.
The clone step is short, and the README notes that git must be present on your system.
git clone https://github.com/GONZOsint/geowifi
cd ./geowifi/The alternative is to download the archive at the main branch zip URL and unzip it, which removes the git dependency for a one-off use.
For a local Python install, the README says to use the pip package manager to install requirements, and the commands create a virtual environment, activate it and install from requirements.txt.
virtualenv geowifi
source geowifi/bin/activate
python3 -m pip install -r requirements.txtThe requirements list is short and readable: PyYAML, requests, folium, google, rich and protobuf pinned to 3.19.5. The pin stands out, because that protobuf release is old and a modern environment may already have a newer one that pip will not replace, which is the kind of conflict worth resolving before you start rather than during the first query.
The Docker route is a single build command.
docker build -t geowifi:latest .The Dockerfile is a python:latest base, copies requirements.txt, installs the requirements with pip, copies the project and sets the entrypoint to python /app/geowifi.py. Because the entrypoint is the script itself, the container is used by passing the search arguments after the image name, which is the same shape as running the script locally.
The command line takes an identifier and two switches
The usage block in the README describes a single positional argument, the identifier, which is the BSSID or SSID of the network to search for, and two options. The first is -s or --search-by, which takes bssid or ssid and defaults to bssid. The second is -o or --output-format, which takes map or json and defaults to map.
The search commands are correspondingly short.
python3 geowifi.py -s bssid <input>python3 geowifi.py -s ssid <input>Under Docker the same arguments follow the image name.
docker run --rm geowifi:latest -s bssid <input>The two output formats answer different needs. JSON is the machine readable one, and it is the format that carries the per-module errors described earlier, so it is the one to use when you are collecting results across many identifiers. The map format draws the located access points on an HTML map, and folium in the requirements is what makes that possible. The README shows both, with a screenshot of the map output.
The repository layout is small and readable: geowifi.py at the root is the entry point, gw_utils/ holds the configuration and the per-database modules, helpers/ has shared code, results/ is where output lands, and tests/ is there for the test suite. There is no packaging metadata to speak of and no published release, so this is a script you run from a checkout rather than a library you depend on.
The boundaries are the databases, the pinned protobuf and the missing licence
There are three limitations worth being concrete about.
The first is that the tool is only as good as the public databases it queries, and those services are free or paid third parties with their own coverage, their own accuracy and their own uptime. The Combain error string in the README's own example, Not enough witooth, is what a sparse database looks like from the outside. An empty result set is a statement about the union of those databases, not about the access point.
The second is the dependency pin. protobuf is pinned to exactly 3.19.5 in requirements.txt, and that pin is old enough to collide with other packages in a shared environment. The virtualenv instructions in the README exist for that reason, and they are not optional advice.
The third is licensing. The repository's licence status is not stated, and there is no LICENSE file among the top level entries, which hold the Dockerfile, README.md, geowifi.py, gw_utils/, helpers/, requirements.txt, results/ and tests/. A missing licence means you do not have permission to redistribute or embed the code, and the project has no GitHub releases either, so there is no version history to pin to beyond the commit you clone.
There is also the OpenWifi row, marked as discontinued, which shows what happens to this class of tool over time. The geolocation databases are volunteer driven and free to query at low volume, and the tool is a thin client over them, so its long term usefulness depends on services the project does not control.
Editorial conclusion
geowifi fits an OSINT investigator who already has a BSSID or SSID from a capture and wants to know where that access point has been seen, without writing eight API clients. It is the wrong tool if you need to collect access points yourself, since it looks things up rather than scanning. Verify first that the databases you care about still answer, because OpenWifi is already marked as discontinued in the table, and read the repository's licensing situation yourself before you use it in paid work, because the licence is not stated.
Frequently asked questions
What does geowifi do?
It searches public Wi-Fi geolocation databases by BSSID or SSID and returns the results from each service. The databases listed are Wigle, Apple, Google, Milnikov, WifiDB, Combain, Freifunk Carte and OpenWifi, with OpenWifi marked as discontinued.
Which API keys does geowifi need?
Three, all set in the config.yaml file in the gw_utils folder: wigle_auth for Wigle, using the Encoded for use value from the Wigle account page, google_api for the Google Geolocation Services, and combain_api for Combain. The remaining databases are queried without credentials.
How do I run geowifi?
The command is python3 geowifi.py with a positional identifier, -s bssid or -s ssid to choose the search key, and -o map or -o json to choose the output. Under Docker the image is built with docker build -t geowifi:latest . and run as docker run --rm geowifi:latest -s bssid <input>.
What happens when a database has no answer?
The JSON output keeps one entry per module, and a database with nothing to return appears as an error object rather than being dropped. The README's example shows combain returning an error and mylnikov returning Object was not found, alongside the modules that returned coordinates.
What licence does geowifi use?
The repository does not state a licence and there is no LICENSE file at the top level, which holds the Dockerfile, README.md, geowifi.py, the gw_utils, helpers, results and tests directories. The project also has no GitHub releases, so the licence and terms have to be confirmed with the author before redistribution or commercial use.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gonzosint-geowifi)Was this useful?