Skip to main content

Search engines and internet maps

Use these tools after vendor and government lists (discovery.md). They find catalog installations that never appear on a gallery page: city CKAN sites, municipal GeoNetwork nodes, university Dataverse hosts.

This page is for public catalog discovery for the registry. It is not a scanner playbook. Do not write internet-wide crawlers in this repository. Query existing search indexes, then confirm each candidate with one or two public GETs.

Agent checklist: agents/discover.md. Platform fingerprints: opendata, geoportals, scientific, metadata, indicators and microdata.

Workflow​

  1. Scope the search: one country, one city, one software.id, one TLD, or one named list URL. Unscoped queries produce more noise than this registry can review. For municipal geoportals, scope to a product tenant list, not every city name.
  2. Duplicate-check exports (datasets.duckdb / full.parquet) and data/scheduled/ before opening dozens of tabs. Match on hostname, not display name. If DuckDB is locked, use Parquet. For a batch of candidates, use python scripts/hunt.py dedupe candidates.jsonl — it reads DuckDB read-only and falls back to parquet automatically.
  3. Run a title / URL query first (Google intitle: / inurl:, Censys html_title, FOFA title=). Then a body / snippet query (ckan-footer-logo, HTTP body). For open-source software that people deploy by forking, search GitHub forks and code search (#github) before an internet-wide body query — the fingerprint is often in the repo, not the HTML title. When that file is also served, use the same string as the FOFA body= query (#common-files). For SaaS viewers, Certificate Transparency often beats Google (%.pozi.com, %.giscloud.com, %.webewid.pl).
  4. Restrict with site:.gov, a national TLD, a Censys location.country_code, or FOFA country="XX".
  5. Confirm the live site with the probe table for that platform. Set software.id only when two signals match. For a batch, python scripts/hunt.py probe candidates.deduped.jsonl --software ckan does polite per-host GETs with encoding-safe title extraction and fingerprint probes.
  6. Add verified finds with add-single --scheduled (or add-batch for a list). Skip demos, docs, GitHub repos, and login-only sites. If the vendor list is exhausted, report 0 missing and stop.
  7. Log the hunt with python scripts/hunt.py log --kind software-instance --target <software-id> --added N --skipped-dupes M --notes "...".

Scripted searches with hunt.py​

scripts/hunt.py is the tested implementation of the plumbing discovery sessions used to rebuild as throwaway scripts. It is a local maintainer/agent CLI — it queries the documented search APIs and probes only candidate hosts, never the open internet.

# FOFA (needs FOFA_EMAIL + FOFA_KEY in the environment)
python scripts/hunt.py search fofa 'title="数据开放" && country="CN"' --out candidates.jsonl --max-pages 2

# Censys Platform v3 (needs CENSYS_API_TOKEN, optional CENSYS_ORGANIZATION_ID)
python scripts/hunt.py search censys 'web.endpoints.http.html_title: "HSLayers"' --out candidates.jsonl

# Duplicate-check against exports (DuckDB read-only, parquet fallback on lock)
python scripts/hunt.py dedupe candidates.jsonl

# Polite probe: per-host serialization, encoding detection, liveness, fingerprints
python scripts/hunt.py probe candidates.deduped.jsonl --software ckan --concurrency 8

# Log the hunt
python scripts/hunt.py log --kind software-instance --target ckan --added 5 --skipped-dupes 12

search retries 429/5xx with exponential backoff and honors Retry-After. probe classifies liveness with the same vocabulary as scripts/check_liveness.py, decodes legacy encodings (GBK, Big5, Cyrillic) for titles, flags 401/403 as auth_required (never bypasses them), and annotates software_id when a fingerprint probe from the apidetect URL maps matches.

What counts as a hit​

Keep a URL when all of these are true:

  • A public catalog UI or harvestable API (dataset list, map catalog, repository search, indicator tables)
  • Country (and subregion for local owners) can be determined from the owner
  • Software is known or explicitly custom

Discard documentation sites, vendor marketing, software forges, single-file download pages, expired domains, and anything that returns 401/403 for the catalog listing.

Google is the highest-yield first pass for named cities and government TLDs. Use Bing or DuckDuckGo with the same operators when Google rate-limits.

Operators that matter​

OperatorMeaningCatalog example
"exact phrase"Words in that order"Powered by CKAN"
intitle:Words in the HTML titleintitle:"GeoNetwork opensource"
inurl:Path or host fragmentinurl:/dataset site:.gov
intext:Words in the page bodyintext:"Powered by OpenDataSoft"
site:Host or TLDsite:.gouv.fr données ouvertes
OREither term"open data" OR "datos abiertos"
-termExclude"CKAN" -site:github.com -site:ckan.org
filetype:File extensionfiletype:xml inurl:GetCapabilities CSW
after: / before:Date filteropendata after:2024-01-01
AROUND(n)Terms near each otherdatos AROUND(3) abiertos

Combine operators. A useful pattern is phrase + path + TLD + exclusions:

"Powered by CKAN" inurl:/dataset site:.gov -site:github.com -site:ckan.org

Language and TLD filters​

Search in the local language. Restrict to the government or national TLD so you do not harvest every blog post about open data.

LanguageCatalog phrasesTypical site:
Englishopen data, data portal, geoportal, data catalog.gov, .gov.uk, .gov.au
Spanishdatos abiertos, catálogo de datos, geoportal.gob.*, .gob.es, .gob.mx, .gob.ar
Frenchdonnées ouvertes, catalogue de données.gouv.fr, .gc.ca
Germanoffene daten, datenportal, geoportal.de, .gv.at, .admin.ch
Portuguesedados abertos, portal de dados.gov.br, .gov.pt
Italiandati aperti, catalogo dati.gov.it
Dutchopen data, dataportaal.overheid.nl
Russianоткрытые данные, геопортал.gov.ru, .рф
Chinese开放数据, 数据开放, 政务数据.gov.cn
Arabicالبيانات المفتوحة.gov.sa, .gov.eg
Japaneseオープンデータ.go.jp, .lg.jp

City and agency names beat generic “open data” queries. Example: datos abiertos "municipalidad" site:.gob.pe.

Query recipes​

Copy and replace the TLD or place name. Platform-specific queries live on the platform pages; these are generic starters.

Open data

("open data" OR opendata OR "data portal") (catalog OR datasets) site:.gov
inurl:/opendata OR inurl:/data OR inurl:/datasets site:.gouv.fr
"datos abiertos" (ayuntamiento OR municipio OR gobernación) site:.gob.mx
inurl:/odweb/ (数据开放 OR "公共数据开放平台") site:.gov.cn

Geoportals

(geoportal OR "geo portal" OR "spatial data" OR INSPIRE) (catalog OR metadata) site:.europa.eu
intitle:geoportal (WMS OR CSW OR GeoNetwork) site:.de

Scientific repositories

("research data" OR "data repository" OR dataverse OR dspace) (datasets OR "dataverse") site:.edu
"institutional repository" (data OR research) site:.ac.uk
("LabKey Server" OR cBioPortal OR InterMine OR "Kadi4Mat" OR NOMAD OR XNAT OR OMERO) (repository OR studies OR archive)
"National Summary Data Page" (e-GDDS OR SDDS OR IMF)

Host patterns

Google site: does not treat data.* as a DNS wildcard. Use inurl: for prefixes, or Certificate Transparency (crt.sh) for opendata. names:

inurl:data. "open data"
inurl:opendata. OR inurl:geoportal.
inurl:hub.arcgis.com
inurl:opendatasoft.com

Noise to exclude​

Add these exclusions once you see the same junk in the first page of results:

-site:github.com -site:gitlab.com -site:sourceforge.net
-site:stackoverflow.com -site:reddit.com -site:wikipedia.org
-site:ckan.org -site:docs.ckan.org -site:opendatasoft.com/blog
-"getting started" -documentation -"quick start" -tutorial

Google often ranks dataset pages and news articles above the catalog homepage. Open the site, then walk up to /, /data, /dataset, or /geonetwork until you have the catalog root. Register the catalog URL, not a single dataset.

GitHub​

Open-source catalog software is often deployed by forking the upstream repository and publishing GitHub Pages or a custom domain. Google, Censys, and FOFA miss those installs when the fingerprint lives in _config.yml, a compose file, or the README rather than the HTML title. Use GitHub for that class of product. Hosted SaaS (ArcGIS Hub, Socrata, OpenDataSoft) still comes from the vendor hostname pattern, not from forks.

Read repository_url on the software YAML. When installations are copies of that repo, build the instance list from GitHub. Do not clone the network. gh api pagination is enough.

Two lists​

GitHub code search does not index most forks. Run both passes or you will miss either the untouched forks or the detached copies.

PassWhat it findsHow
ForksCopies that stayed attached to the upstream repoGET /repos/{owner}/{repo}/forks?per_page=100 (paginate)
Code searchRenames, “based on” repos, and forks GitHub has detachedA product-specific string in a file operators edit

Code search needs a string that only this product writes, not the product name alone. filename:_config.yml, a theme key, a Docker Compose service, or a layout path from the platform page. The JKAN pair is the worked example for a GitHub Pages app: forks of timwis/jkan, then jkan_theme filename:_config.yml (discovery-opendata.md). A wider README phrase ("backend-free open data portal") finds more repos and more empty clones.

CKAN is the server-app shape. Forks of ckan/ckan and ckan/ckan-docker keep CKAN_SITE_URL on localhost. Search the committed config instead: ckan.site_url in ckan.ini (2.9+) and production.ini (2.8), or CKAN_SITE_URL=https:// in .env and READMEs (discovery-opendata.md).

Common files, then FOFA​

Take the code-search string from a file the upstream repo ships (_config.yml, Gemfile, index.html, a layout, local.cfg). When that same string is written into the HTML, it is also the FOFA body= query. A short product-name body query is a weak fingerprint: in September 2026 body="NADA" matched about 1.4 million unrelated hosts, and body="Powered by Datasette" matched none because the footer template splits the words around an <a> tag.

Forks of a server framework (CKAN, Datasette, Omeka S, DSpace, VuFind, Hyrax) are the software, not a portal list. Search the committed config or the served string from the layout. Forks are the portal list for a GitHub Pages app (JKAN, OpenSDG) and for a viewer people copy (mviewer, STAC Browser).

software.idFileSearch
opensdgopen-sdg-site-starter _config.yml, GemfileGitHub remote_theme: open-sdg/open-sdg filename:_config.yml; FOFA body="jekyll-open-sdg-plugins"
stacbrowserindex.html, config.jsGitHub forks of radiantearth/stac-browser; read catalogUrl; FOFA body="STAC Browser doesn't work properly"
mviewerindex.htmlGitHub forks of geobretagne/mviewer; FOFA body="css/mviewer.css"
dspacedspace/config/local.cfg.EXAMPLE, dspace-angular head-tag.service.tsGitHub "dspace.ui.url = https://" filename:local.cfg; FOFA body="generator\" content=\"DSpace"
datasettedatasette/templates/base.htmlFOFA body="application/json+datasette"
omekasapplication/view/layout/layout.phtmlFOFA body="Powered by Omeka S"
dataversesrc/main/webapp/dataverse.xhtmlFOFA body="dataverse.xhtml"
hyraxapp/views/layouts/_generator_meta_tag.html.erbFOFA body="Samvera Hyrax"
inveniordminvenio_app_rdm/.../footer.htmlFOFA body="app-rdm-footer"
vufindthemes/bootstrap5/templates/layout/layout.phtmlFOFA body="VuFind.path"
nadathemes/nada/footer.php, themes/nada52/footer.phpFOFA body="nada-logo"
alephui/public/index.htmlFOFA body="data-api-endpoint=\"/api/2/\""
geonodegeonode/templates/base.htmlFOFA body="geonode/css/base.css"
mapstoreweb/client/indexTemplate.htmlFOFA body="_ms2_init_text"
qwc2index.htmlFOFA body="assets/css/qwc2.css"
geoblacklightapp/views/catalog/_home_text.html.erbFOFA body="geoblacklight-version"
eprintslib/templates/default.xmlFOFA body="ep_tm_header"
pygeoapipygeoapi/templates/_base.html, pygeoapi-config.ymlFOFA body="static/img/pygeoapi.png"; GitHub filename:pygeoapi-config.yml
pxwebPXWeb/PxWeb.MasterFOFA body="main-pxweb.css"
lizmaplizmap/modules/view/templates/map.tplFOFA body="lizmap-navbar"
mapbendersrc/Mapbender/CoreBundle/Resources/publicFOFA body="bundles/mapbendercore"
invenioinvenio_theme/.../footer.htmlFOFA body="http://inveniosoftware.org"
wikibaseview/resources/templates.phpFOFA body="wikibase-title"
phaidrasrc/phaidra-ui/app.htmlFOFA body="This repository is powered by PHAIDRA"
oskariservlet-map/.../index.jspFOFA body="oskari.min.css"
galaxytemplates/js-app.makoFOFA body="Javascript Required for Galaxy"
opuspublic/layouts/opus4/common.phtmlFOFA body="layouts/opus4"
librecatviews/header.ttFOFA body="BEGIN header.tt"
magdamagda-web-client/public/index.htmlFOFA body="/api/v0/content/favicon.ico"
udataudata_front/.../footer.htmlFOFA body="github.com/opendatateam/udata/"
supersetsuperset/templates/superset/spa.htmlFOFA body="superset-theme-mode"
tripaltripal/css/tripal.cssFOFA body="tripal.css"
mytardistardis_portal/templates/.../portal_template.htmlFOFA body="github.com/mytardis/mytardis"
korpapp/index.htmlFOFA body="You need JavaScript to run Korp."
igo2src/index.htmlGitHub forks of infra-geo-ouverte/igo2; code search splash-screen__filmstrip; FOFA body="splash-screen__filmstrip"
xnatxnat-templates/navigations/htmlOpen.vmFOFA body="xnat-templates/navigations/htmlOpen"
terriaapps/terriamap/wwwroot/index.ejsFOFA body="class=\"terria\""
scicatsrc/index.htmlFOFA body="SciCat metadata catalogue"
weko3weko_theme/.../header.htmlFOFA body="weko_admin/quill.snow.css"
omerowebclient/templates/webclient/login.htmlFOFA body="ome.login.css"
bexis2Themes/Default/Layouts/_Layout.cshtmlFOFA body="bundles/bexis"
mycoremir-module/.../mir-common-layout.xslFOFA body="mir-lang"
mickaCatalog/templates/default/@layout.latteFOFA body="micka.css"
intermineintermine/webapp/.../layout.jspFOFA body="intermine.Service"
fedorafcrepo-webapp/.../index.htmlFOFA body="fcrepo-favicon.png"
gsimapsindex.htmlFOFA body="css/gsimaps.css"
threddsWEB-INF/templates/catalog.htmlFOFA body="tds.css"
liferayfrontend-theme-classic/.../portal_normal.ftlFOFA body="http://www.liferay.com"
symbiotaincludes/head_template.phpFOFA body="symbiota/header.css"
cbioportalmy-index.ejsFOFA body="cbioportal-frontend"
fairdatapointpublic/index.htmlFOFA body="fdp-client doesn't work properly"
geonetworkcatalog/views/api/index.html, catalog/locales/en-core.jsonFOFA body="gn_search_default"; also body="gn-bottom-bar", body="datahub-root", body="GeoNetwork opensource"
labkeybootstrap/pageTemplate.jspFOFA body="lk-body-ct"
pycswpycsw/templates/_base.htmlFOFA body="pycsw-logo-vertical.png"
mapserversrc/maperror.cFOFA body="MapServer version"
opendaphyraxhyrax/xsl/threddsCatalogPresentation.xslFOFA body="OPeNDAP Hyrax"
hubzeroen-GB.tpl_kameleon.iniFOFA body="http://hubzero.org"
pydapwsgi/templates/index.html, 3.2 pydap-listingFOFA body="pydap-listing"; also body="http://pydap.org/" and body="OPeNDAP pydap"
dataonesrc/index.htmlFOFA body="configuration file for MetacatUI"
clowderapp/views/main.scala.htmlFOFA body="clowderframework.org"
ramaddaresources/web/jsimports.htmlFOFA body="ramadda.js"
metasharemetashare/templates/base.htmlFOFA body="metashare/js/metashare.js"
shanoirshanoir-ng-front/src/index.htmlFOFA body="/shanoir-ng/"
nomadgui/public/index.htmlFOFA body="close all NOMAD tabs"
iptWEB-INF/pages/inc/footer.ftlFOFA body="GBIF-2015-standard-ipt.png"
vivothemes/wilma/templates/footer.ftlFOFA body="vivoweb.org"
frostserverFROST-Server.MQTTP/.../index.htmlFOFA body="FROST-Server"
geoserverweb/app/.../index.htmlFOFA body="GeoServer admin console"
mapproxyservice/templates/demo/static.htmlFOFA body="MapProxy Demo"
umapumap/templates/base.htmlFOFA body="umap/favicons"
dandiweb/index.htmlFOFA body="DANDI Archive doesn't work properly"
breedbasemason/site/footer/body.masFOFA body="solgenomics/sgn"
nextstrainstatic-site/components/footer/index.tsxFOFA body="attribution to nextstrain.org"
opencontextbootstrap_vue/page_footer.htmlFOFA body="Open Context is a publishing service"
gintemplates/base/footer_gin_brand.tmplFOFA body="doi.org/10.17616/R3SX9N"
shogunshogun-boot/.../index.htmlFOFA body="terrestris.github.io/shogun"
tailormapprojects/app/src/index.htmlGitHub "<title>Tailormap</title>" "<tm-root></tm-root>"; FOFA body="<tm-root></tm-root>" && title="Tailormap"
obibamicamica-webapp/.../footer.ftlFOFA body="www.obiba.org"
datahubprojectdatahub-web-react/index.htmlFOFA body="A Metadata Platform for the Modern Data Stack"
hajkapps/client/index.htmlFOFA body="Hajk - open source webGIS"
sitmunsitmun-viewer-app src/index.html; classic inicio.jspFOFA body="SITMUN Service worker registered"; classic body="library/dojo/themes/sitmun" and body="/sitmun/inicio.jsp"
gc2public/apps/viewer/index.htmlFOFA body="window.MapCentia"
biodare2static/index.htmlFOFA body="BioDare2 - circadian period analysis"
cellxgenefrontend/src/pages/_app.tsxFOFA body="Cellxgene Data Portal"
clldsrc/clld/web/templates/app.makoFOFA body="clld-disclaimer"
massbankMassBank-web/.../Index.jspFOFA body="MassBank Consortium"
databuspublic/templates/footer.ejsFOFA body="Global and Unified Access to Knowledge Graphs"
ontoportallayouts/_footer.html.hamlFOFA body="ontoportal"
lovdsrc/class/template.phpFOFA body="LOVD v."
jacqoutput.new/index.phpFOFA body="JACQ_LOGO.png"
proteosafeLiveSearch/.../index.jspFOFA body="General ProteoSAFe scripts"
molgenisapps/tailwind-components/.../FooterComponent.vueFOFA body="Created with MOLGENIS"
opengeoportaltemplates/ogp_home.htmlFOFA body="OpenGeoportal.Config"
specifyPortalApp/index.htmlFOFA body="resources/css/thumb-view.css"
reearthweb/index.html, published publishedAppProviderGitHub forks of reearth/reearth-visualizer and reearth/reearth-cms; FOFA body="publishedAppProvider"; CMS body="Re:Earth CMS"
gobiertolayouts/_gobierto_footer.html.erbFOFA body="window.gobiertoAPI"
origobuild/index.htmlFOFA body="var origo = Origo"
yodathemes/vu/index.htmlFOFA body="Yoda is a share-collaborate environment"
gisquickclients/gisquick-web/public/index.htmlFOFA body="gisquick-web doesn't work properly"; /map/ mounts also body="/map/static/js/chunk-vendors"
instdbVue public/index.html noscriptFOFA body="instdb-web doesn't work properly"
argenmapindex.htmlFOFA body="src/js/components/openfiles/openfiles.css"
miramonsrc/index.htm, src/examples/*.jsonGitHub forks of grumets/MiraMonMapBrowser; read ServidorLocal; FOFA body="StartMiraMonMapBrowser"
atlasmapperclientResources/amcTemplates/index.html.ftlFOFA body="atlasmapperVer"
geonatureatlas/templates/core/assets_header.htmlFOFA body="/static/css/atlas.css"
dhis2app-platform shell/index.html; dhis-web-api/.../login.htmlFOFA body="dhis2-app-root"; also body="dhis-web-commons"
52northsosWEB-INF/views/common/header.jspFOFA body="static/css/52n.css"
geomapfishcontribs/gmf/apps/desktop/index.html.ejsFOFA body="gmf-app-data-panel"
shinyinst/www/shared/shiny.min.cssFOFA body="shared/shiny.min.css"
gvsigonlinegvsigol_core/templates/base.htmlFOFA body="gvsigOL.css"
datafairui/index.htmlFOFA body="simple-directory/api/sites"
gbdwebsuitedata/web/demo.html, client login gwsUsername, /gws-client/gws-start-FOFA body="webSystemAsset"; also body="gwsUsername" and body="/gws-client/gws-start"; GitHub "gbdconsult/gws-server"
istatdatabrowserdatabrowser/index.htmlFOFA body="webpackJsonpdata-browser"
mxsigmxsig/index.htmlFOFA body="mdm6ico.png"
mfgeoadmin3src/index.mako.htmlFOFA body="GaMainController"
ampamp-boilerplate/.../about-template.htmlFOFA body="ampTemplate"
openequellacom.equella.core/.../ResourcesService.javaFOFA body="com.equella.core"
wis20boxwis2box-ui/index.htmlFOFA body="WIS 2.0 node in a box"
flatdocker/flat/islandora/template.phpFOFA body="flat_bootstrap_theme"
synapsesrc/main/webapp/Portal.htmlFOFA body="info@sagebase.org"
geomooseexamples/desktop/index.html, geomoose.htmlGitHub forks of geomoose/gm3; mapfile_root filename:config.js; FOFA body="geocode-osm.js"; also body="user_catalog.css"
g3wsuiteclient/templates/client/index.htmlFOFA body="g3wsuite_logo.png"
fellesdatakatalogsrc/entrypoints/main/index.htmlFOFA body="cms.fellesdatakatalog.digdir.no"
materialscloudmaterialscloud-discover/index.html.j2FOFA body="mcloud_theme.min.css"
opendatacubecubedash/templates/layout/base.htmlGitHub forks of opendatacube/datacube-explorer; filename:ingress.yaml datacube-explorer; FOFA body="id=\"datacube-version\""
ckanckan/templates/footer.htmlFOFA body="ckan-footer-logo"
vcmapindex.htmlFOFA body="vcs-ui"
datacubewsdatacube_ows/templates/index.htmlFOFA body="datacube-ows"
hydrosharetheme/templates/base.htmlFOFA body="hydroshare_core.css"
dkandata-catalog-app/index.htmlFOFA body="DKAN is an open-source data management platform"
statplanetStatPlanet_Cloud.htmlFOFA body="statsilk-container"
geotrekfrontend/src/pages/_document.tsxFOFA body="--color-primary1-default"
grandchallengepartials/script.htmlGitHub forks of DIAGNijmegen/rse-grand-challenge; datatables.defaults.mjs; FOFA body="js/datatables.defaults.mjs" && domain!="grand-challenge.org"
bodikodcsckanext/bodik_theme/templates/base.htmlFOFA body="bodik_odcs.css"
andinockanext/gobar_theme/templates/footer.htmlFOFA body="gobar-footer-grid"
checklistbankindex.htmlFOFA body="<title>ChecklistBank</title>"
terristoryfront/index.htmlFOFA body="base de données TerriSTORY"
statsuitei18n/en.jsonFOFA body=".Stat Suite"
kadi4matkadi/templates/base.htmlFOFA body="window.kadi"
piveauindex.htmlFOFA body="<title>Piveau UI</title>"
lkodsrc/app/metatags.jsonFOFA body="Procházejte a stahujte datové sady"
openwisjsp/banner.jspFOFA body="images/openwis/header-left.jpg"
resourcecontractslayout/partials/head.blade.phpFOFA body="css/new-rc.css"
webmapviewerpackages/mapviewer/index.htmlFOFA body="Maps of Switzerland - Swiss Confederation - map.geo.admin.ch"
codalabapps/web/templates/base.htmlFOFA body="<title>CodaLab -"
codabenchsrc/templates/base.htmlFOFA title="Codabench"
evalaifrontend/base.htmlFOFA body="ng-app=\"evalai\""
openspendingspendb/templates/layout.htmlFOFA body="explore, visualize and track government spending"
brainlifeui/index.htmlFOFA body="<title>brainlife</title>"
ourworldindatasite/SiteFooter.tsxFOFA body="Teaching with OWID"
smartmetserversource/AsyncConnection.cpp, smartmet-{iso2} portainer composeGitHub routers.smartmetserver.rule; FOFA header="SmartMet Server" and body="SmartMet Server"
dachsresources/web/xsl/dachs-xsl-config.xslFOFA body="gavo_dc.css"
iudxdocs/apidoc.html, UI index.htmlFOFA body="DX Catalogue API Docs"; UI title="IUDX | Indian Urban Data Exchange" and body="IUDX UI Team"; GitHub ingress hosts in datakaveri/iudx-deployment
masterportalportal/master/index.htmlFOFA body="masterportal-root"
kvwmapfunktionen/gui_functions.jsFOFA body="funktionen/gui_functions.js"
mediatumgenerator metaFOFA body="mediatum - a multimedia content repository"
klimadashboardmuensterOpen CoDE creditFOFA body="klimadashboard-muenster"
minervapages/_document.tsxFOFA body="/minerva/config.js"
opengdcthemes/custom/dexes/templates/page.html.twigFOFA body="themes/custom/dexes"
ensemblhtdocs/info/about/ensembl_powered.htmlFOFA body="/img/empowered.png"
ovieindex.htmlGitHub js/libs/jquery.ntm/js/jquery.ntm.js filename:index.html (client is on INEGI GitLab; title phrase finds linked deployments); FOFA body="js/libs/jquery.ntm/js/jquery.ntm.js"
onegeosuitegatsby-config.jsFOFA body="Onegeo Portal"

September 2026 FOFA hit counts for these strings are on the platform pages, next to the full query tables.

gh api --paginate "repos/timwis/jkan/forks?per_page=100"
gh api -H "Accept: application/vnd.github+json" \
"search/code?q=jkan_theme+filename:_config.yml&per_page=100"

From a repository to a catalog URL​

Register the published site, not the github.com repository.

  • Use homepage when it is a real catalog. Ignore it when every fork still carries the upstream marketing URL (https://jkan.io).
  • Otherwise try https://{owner}.github.io/{repo}/, or https://{owner}.github.io/ when the repository is {owner}.github.io.
  • Read CNAME when Pages uses a custom domain.
  • Probe the platform GET (/data.json for JKAN, the package or CSW URL for other stacks). Keep a site that lists datasets. Drop the upstream repo, docs, demos, empty forks, and templates whose only entry is the stock sample dataset.
  • Several path tenants on one github.io host are separate catalogs. Set --id so the host-only id does not collide (datascientiafoundation.github.io/LiveData/ and /LiveDataNUM/).
  • A custom domain and a github.io URL that serve the same dataset list are one catalog. Keep the public hostname.

Censys​

Censys Platform indexes hosts, certificates, and web properties. It is useful when Google does not list a site (no inbound links, robots-blocked HTML, IP-only services). If Censys search is not on your plan or MCP is not connected, use FOFA with the same title / body / country filters.

Create a free or research account. Use the web properties dataset for catalogs (they are websites). Use hosts when you need a product fingerprint on a port (GeoServer, ArcGIS Server). Use certificates for hostname patterns such as opendata.*.

Do not export huge unscoped result sets. Filter by country or software, then review hostnames one by one.

Query language (Platform)​

Censys Platform uses CenQL. : is tokenized full-text search. = is an exact match. Prefer web properties for catalog UIs:

GoalField (web properties)Field (hosts)
HTML titleweb.endpoints.http.html_titlehost.services.endpoints.http.html_title
HTML body (first 64 KB)web.endpoints.http.bodyhost.services.endpoints.http.body
Software productweb.software.producthost.services.software.product
Countryweb.location.country_codehost.location.country_code
Hostname / nameweb.nameshost.dns.names

Official syntax: Censys Query Language. Field names change between Legacy Search and Platform; if a query returns a parse error, switch the dataset tab or check the field browser in the UI.

Starter queries (Platform)​

Web properties — titles and body snippets

web.endpoints.http.html_title: "CKAN"
web.endpoints.http.body: "ckan-footer-logo"
web.endpoints.http.html_title: "GeoNetwork"
web.endpoints.http.body: "GeoNetwork opensource"
web.endpoints.http.html_title: "Socrata"
web.endpoints.http.body: "OpenDataSoft"
web.endpoints.http.body: "LabKey"
web.endpoints.http.body: "cBioPortal"
web.endpoints.http.body: "Kadi4Mat"
web.endpoints.http.body: "/odweb/"
web.software.product: "GeoServer"
web.names: "opendata"

Hosts — products that listen on a port

host.services.software.product = "GeoServer"
host.services.software.product = "ArcGIS"
host.services: (software.product = "GeoServer" and endpoints.http.html_title: "GeoServer")
host.location.country_code = "FR" and host.services.endpoints.http.html_title: "CKAN"

Certificates — hostname patterns

cert.parsed.names: "opendata"
cert.parsed.names: "geoportal"
cert.parsed.names: "data.gov"

Intersect with country whenever the UI allows it. Example: French CKAN-like titles:

web.location.country_code = "FR" and web.endpoints.http.html_title: "données"
web.names: ".gouv.fr" and web.endpoints.http.body: "ckan"

Legacy Search (older UI)​

If you still have access to search.censys.io Legacy Search, the equivalent fields are services.http.response.html_title, services.http.response.body, and services.software.product:

services.http.response.html_title: "CKAN"
services.http.response.body: "ckan-footer-logo"
services.software.product: GeoServer
location.country_code: FR

How to turn a Censys hit into a registry URL​

  1. Copy the hostname (prefer the certificate or web-property name, not a raw IP).
  2. Try https://{hostname}/ first, then the platform path (/dataset, /geonetwork, /dataverse).
  3. Duplicate-check the hostname in DuckDB.
  4. Probe the public API path from the platform guide.
  5. Skip hosts that only serve a login form, a default web-server page, or an internal dashboard.

Censys records IPs that may host many vhosts. Always confirm the catalog URL in a browser or with a GET that includes a Host header / HTTPS name. Do not register a bare IP as link.

Shodan​

Shodan is the other large internet map. Filters that help:

FilterUse
http.title:HTML title
http.html:Body snippet
http.component:Detected component
product:Service product
org: / ssl:Organisation or cert CN
country:ISO country
hostname:Reverse DNS / vhost
http.title:"CKAN" country:DE
http.html:"ckan-footer-logo"
http.title:"GeoNetwork" country:FR
product:GeoServer country:ES
http.html:"ArcGIS REST Services Directory"
http.title:"Dataverse" hostname:edu
ssl.cert.subject.CN:opendata

Same review rules as Censys: hostname over IP, public catalog UI, no auth bypass.

FOFA​

FOFA is an internet map in the same class as Censys and Shodan. Use it as the Censys alternative when any of these is true:

  • Censys Platform search is not on the plan, or the official Censys MCP is not connected
  • The hunt is East Asia (China, Japan, Korea, Taiwan, Hong Kong) — FOFA’s index is often denser there
  • You already have FOFA_EMAIL / FOFA_KEY and want the same title / body / country filters in FOFA syntax

Same job as Censys: find catalog UIs that Google does not list. Same review rules: hostname over IP, public catalog UI, no auth bypass. Do not export huge unscoped result sets. Filter by country or software, then review hostnames one by one.

API and agent setup: discovery-agent-tools.md. Official syntax: FOFA rule list (sign-in). Free and low plans often cannot search body= or header= over the API — fall back to title=, host=, domain=, app=, and cert=.

Query language​

FOFA uses field="value" with && (AND), || (OR), and != (NOT). Values are quoted. Translate any Censys row in the platform guides with this table. Software pages include a FOFA row for each Censys query; use this table when you need a variant (country, TLD) that is not listed.

GoalFOFACensys (web properties)
HTML titletitle="CKAN"web.endpoints.http.html_title: "CKAN"
HTML bodybody="ckan-footer-logo"web.endpoints.http.body: "ckan-footer-logo"
HTTP headerheader="X-Socrata"(headers / body)
Detected productapp="GeoServer"web.software.product: "GeoServer"
Countrycountry="PT"web.location.country_code = "PT"
Hostname fragmenthost="opendata"web.names: "opendata"
Registrable domaindomain="opendatasoft.com"web.names: "opendatasoft.com"
Certificate namecert="opendata"cert.parsed.names: "opendata"
HTTPS onlyprotocol="https"prefer HTTPS web-property names

host= is a substring match, so host=".gouv.fr" is the usual TLD filter. Combine with country whenever the query would otherwise be global.

domain= is the registrable domain (arcgis.com), not a product hostname. A row for city.hub.arcgis.com has domain = arcgis.com, so domain!="hub.arcgis.com" does not drop ArcGIS Hub tenants. Exclude that SaaS with domain!="arcgis.com", and find the tenants themselves with host="hub.arcgis.com" (substring) or domain="opendata.arcgis.com". Custom-domain Hub shells are body="hubcdn.arcgis.com/opendata-ui" && domain!="arcgis.com" — see ArcGIS Hub. Short body tokens (body="opendata-ui", body="hub.js") are weak fingerprints.

Path tenants. host= and domain= return one asset per host. A product that puts every city on one host (app.gisonline.cz/{city}) does not yield one FOFA row per city. Search the tenant host as a body backlink (body="app.gisonline.cz" && domain!="gisonline.cz") and read the path from the referring page. See GisOnline.

Scheme stored in host. Some rows set host to https://app.example.cz rather than app.example.cz. protocol="https" then returns 0. Filter those with port="443".

body= query versus body field. A body="..." query can succeed on a plan that still rejects fields containing body (FOFA error 820001, no permission to return the body). Keep fields to host,link,title,domain,port and open the live page for the path.

Worked translations

CensysFOFA
web.location.country_code = "FR" and web.endpoints.http.html_title: "données"title="données" && country="FR"
web.names: ".gouv.fr" and web.endpoints.http.body: "ckan"host=".gouv.fr" && body="ckan"
web.names: "opendatasoft.com"domain="opendatasoft.com"
host.services.software.product = "GeoServer"app="GeoServer"
web.endpoints.http.body: "/odweb/"body="/odweb/"

Starter queries​

title="CKAN"
body="name=\"generator\" content=\"ckan"
body="ckan-footer-logo"
body="profiles/dkan"
body="DKAN is an open-source data management platform"
title="CKAN" && country="PT"
body="ckan-footer-logo" && country="JP"
title="GeoNetwork"
body="GeoNetwork opensource"
app="GeoServer"
title="Socrata"
body="OpenDataSoft"
domain="opendatasoft.com"
host="opendata"
cert="opendata"
title="数据开放" && country="CN"
body="/odweb/" && title="数据开放"
host="data.gxzf.gov.cn"
title="Dataverse"
body="DSpace"
title="PxWeb"

Paste these in the FOFA web search box, or Base64-encode them for the API (qbase64). Platform pages include a few FOFA rows where the query is not a 1:1 Censys translation or where FOFA coverage is stronger (ODWeb, Guangxi, Tianditu, MapGIS, Hyrax).

CKAN’s default footer splits “Powered by” and “CKAN” around the class ckan-footer-logo, so body="Powered by CKAN" is a weak CKAN query (85 hosts in September 2026, led by ckan.org). Prefer body="name=\"generator\" content=\"ckan" and the config-file queries in discovery-opendata.md. body="ckan.js" and js_name="ckan.js" miss current installs.

DKAN has no app="DKAN". body="DKAN" is a mention search (2261 hosts in September 2026). body="dkan.js" and js_name="dkan.js" return 0. Prefer body="profiles/dkan" for the Drupal 7 profile and body="DKAN is an open-source data management platform" for the DKAN 2 React shell, then the file queries in discovery-opendata.md.

Tablion has no app="Tablion". body="Tablion" is a mention search (38 hosts in September 2026) and also matches the Byzantine garment of that name. domain="tabliondata.com" only sees the marketing redirect. Tenant apps are {org}.tabliondata.com; find the names with %.tabliondata.com in Certificate Transparency, then the chrome queries in discovery-opendata.md. body="aristotle_mdr" is the metadata registry, not Tablion.

How to turn a FOFA hit into a registry URL​

  1. Prefer host, domain, or link in the result, not ip.
  2. Try https://{host}/ first (drop :443; keep a non-443 port only if the catalog really listens there), then the platform path (/dataset, /geonetwork, /dataverse, /odweb/).
  3. If the hit is a site that only links the product, follow that product URL. Do not register the referring homepage.
  4. Duplicate-check the hostname in DuckDB. For a path tenant, duplicate-check the full path, not the shared host.
  5. Probe the public API path from the platform guide.
  6. Skip hosts that only serve a login form, a default web-server page, or an internal dashboard.

FOFA often returns the same catalog on ports 80 and 443, or several vhosts on one IP. Deduplicate by hostname before probing. Never set link to a bare IP.

ZoomEye and similar maps​

These indexes overlap FOFA for East Asian and some European hosts that Google ranks poorly.

ZoomEye:

title:"CKAN"
http.body:"ckan-footer-logo"
app:"GeoServer"

Netlas and Onyphe expose similar title / body / country filters. Translate the same phrases; do not expect identical field names.

urlscan.io searches recently crawled pages (good for new city portals):

page.title:"CKAN"
page.title:"GeoNetwork"
page.url:"opendata" AND page.title:"data"
page.url:"/api/3/action" AND filename:json

PublicWWW and nerdydata search HTML source across the web. They catch footer strings that Google tokenizes away:

"ckan-footer-logo"
"od_80x15_blue.png"
"Powered by CKAN"
"GeoNetwork opensource"
"ods-theme"
"soda.demo.socrata.com" # exclude this; look for soda. hosts instead
"dataverse.js"

Export hostnames, then duplicate-check. These services are noisy: always open the live catalog.

Certificate Transparency and DNS​

Catalogs often sit on predictable names. Search Certificate Transparency rather than brute-forcing DNS.

crt.sh (SQL-like % wildcards):

%.opendata.%
opendata.%
data.%.gov.%
geoportal.%
geonetwork.%
%.hub.arcgis.com
%.opendatasoft.com
%.pozi.com
%.giscloud.com
%.spatial.t1cloud.com
%.webewid.pl

Censys certificates and Cloudflare Radar / CT can list the same names.

Useful hostname prefixes: data., opendata., datos., donnees., geo., geoportal., metadata., catalog., ckan., dkan., gis., maps., indicators., stats., microdata., nada..

A certificate name is not a catalog. Resolve it, then confirm a catalog UI.

Common Crawl and web archives​

When a site is gone from Google but you need the catalog root:

Prefer the live URL for link. Use archives only to recover a name or to mark status: inactive.

Technology lookup (verify, not hunt)​

Once you have a hostname, these tools confirm software.id. They are weak for hunting unknown sites.

ToolWhat it tells you
Wappalyzer / browser extensionJS frameworks, CMS, sometimes CKAN / Socrata
BuiltWithSimilar, plus historical tech
Browser View source / Network tab/api/3, /srv/api, /api/explore, /arcgis/rest
https://host/robots.txt and /sitemap.xmlHidden API or catalog paths
HTTP headersX-Socrata-*, Server:, cookies named ckan / geonetwork

Cross-check at least two signals before setting software.id. If nothing matches, use custom.

Official and community lists (still first)​

Search engines miss less when you start from a list. Highest yield:

SourceTypical software
CKAN ecosystemckan (also scripts/sync_ckan_ecosystem.py)
DatashadesCKAN and others
data.europa.eu cataloguesNational EU catalogs
GeoNetwork gallerygeonetwork
INSPIRE geoportalEuropean SDI catalogs
re3dataScientific repositories
OpenAIRE Graph data sourcesScientific repositories (scripts/extract_openaire_portals.py)
Dataverse installationsdataverse
STAC IndexSTAC
ArcGIS Hubarcgishub
Open Data InceptionMixed open data
ROARRepositories (eprints, dspace, …)
OpenDOAROpen-access repositories by country/software
GBIF IPTipt
ODIS catalogueOcean catalogs
CoreTrustSealCertified repos with a public dataset catalog
WMO WIS2 GDCMeteorological node catalogs
National harvest APIsOrigin catalogs behind data.go.id, datos.gob.es, opendata.swiss, data.gov.ru, search.open.canada.ca, data.gouv.fr, govdata.de, data.go.kr, dane.gov.pl

More lists and the hunt-pattern table: discovery.md, discovery.md.

Duplicate check (do this constantly)​

SELECT id, uid, name, link, catalog_type, status,
software.id AS software_id
FROM catalogs
WHERE lower(link) LIKE '%example.gov%'
OR id = 'examplegov';

Match www vs bare host, http vs https, and /data vs /. DUPLICATE_LINK / DUPLICATE_LINK_NORMALIZED fail quality checks.

Conduct​

  • Public catalog metadata only. Stop on 401/403. Do not follow login forms or guess API keys.
  • Space out live GETs (about one to two seconds between hosts). Search-engine queries do not hit the catalog until you verify.
  • Respect robots.txt and site terms when you fetch the candidate itself.
  • Do not collect personal data or non-public APIs.
  • Do not add internet-wide scanners, mass port scans, or recursive crawlers to this repository.