Cada ficheiro é JSON Lines comprimido com zstd, com um domínio por linha. Veja aqui como o abrir, fazer-lhe perguntas e carregá-lo no seu stack. Cada receita foi executada na amostra gratuita de 10 000 linhas, e o resultado que vê foi o que o comando devolveu.
Formato
JSON Lines, comprimido com zstd
.jsonl.zst
Uma linha por
Domain, todas as chaves sempre presentes
os valores podem ser null
Nome do ficheiro
Dataset e data da exportação
all-data-2026-10-16.jsonl.zst
Atualização
Uma nova exportação todos os dias
as mesmas colunas todos os dias
1 · O que descarrega
O que descarrega
Todos os datasets da webatla são JSON Lines: um domínio por linha, um objeto JSON por linha. Os ficheiros pagos são comprimidos com zstd.
Ficheiro
O que contém
Formato
Dataset completo
Todas as linhas do dataset
.jsonl.zst
Corte
Todas as linhas de um TLD, sufixo de TLD, país (por IP) ou tecnologia, com os mesmos campos do ficheiro completo
.jsonl.zst
Amostra gratuita (10 000 linhas)
As primeiras 10 000 linhas do ficheiro completo
.jsonl simples, sem compressão
Amostra de 20 linhas nas páginas de TLD, país e tecnologia
Linhas dessa entidade, com os mesmos nomes de campos do ficheiro pago. Mostra algumas das linhas mais completas, não linhas aleatórias.
na página
Descarregue um corte em vez de filtrar o ficheiro completo
Se precisa de uma zona, um país ou uma tecnologia, o corte já vem filtrado e é muitas vezes mais pequeno.
A amostra gratuita mostra o formato, não uma mistura típica
A maioria dos ficheiros está ordenada por sufixo de TLD, por isso as primeiras 10 000 linhas cobrem apenas alguns sufixos do início do alfabeto, e .com não é um deles. Um filtro que não devolve nada na amostra pode devolver milhões de linhas no ficheiro completo. Use a amostra para montar e testar os seus comandos. Eles correm sem alterações no ficheiro pago.
2 · Abrir o ficheiro
Espreitar lá dentro sem descomprimir
Todas as ferramentas aqui leem o ficheiro comprimido em fluxo. A única diferença entre a amostra e o ficheiro pago é a forma como o abre.
import io, json, zstandard
with open("dns-2026-10-16.jsonl.zst", "rb") as fh:
stream = zstandard.ZstdDecompressor().stream_reader(fh, read_across_frames=True)
for line in io.TextIOWrapper(stream, encoding="utf-8"):
row = json.loads(line)
mx = (row["DNS records"] or {}).get("MX") or []
if any((m.get("host") or "").lower().endswith(".google.com") for m in mx):
print(row["Domain"])
Primeiro a resposta, a consulta DuckDB a um clique de distância. Abra um terminal na pasta com o ficheiro descarregado, escreva duckdb e cole a consulta.
Ordenadas por PR value, guardadas como woocommerce-de.csv com 12 linhas. Um CSV que o seu CRM ou folha de cálculo abre.
Mostrar a consulta
COPY (SELECT Domain, "PR value" FROM read_json('technologies-2026-10-16.jsonl.zst',
columns = {Domain: 'VARCHAR', "Country by IP": 'VARCHAR',
Technologies: 'JSON', "PR value": 'DOUBLE'})
WHERE "Country by IP" = 'DE' AND list_contains(CASE json_type(Technologies)
WHEN 'OBJECT' THEN json_keys(Technologies)
WHEN 'ARRAY' THEN from_json(Technologies, '["VARCHAR"]') END, 'WooCommerce')
ORDER BY "PR value" DESC
) TO 'woocommerce-de.csv';
Que construtor de sites está por trás de mais websites?
Saída real da amostra de 10 000 linhas
WordPress628 · 80,6%
Wix52 · 6,7%
Squarespace45 · 5,8%
Drupal22 · 2,8%
Webflow20 · 2,6%
Joomla12 · 1,5%
Quota entre estes seis construtores, não entre todos os websites. Execute-a num corte de um país para comparar um mercado.
Mostrar a consulta
SELECT tech, count(*) AS sites,
round(100 * count(*) / sum(count(*)) OVER (), 1) AS pct
FROM (SELECT unnest(CASE json_type(Technologies)
WHEN 'OBJECT' THEN json_keys(Technologies)
WHEN 'ARRAY' THEN from_json(Technologies, '["VARCHAR"]') END) AS tech
FROM read_json('technologies-2026-10-16.jsonl.zst', columns = {Technologies: 'JSON'}))
WHERE tech IN ('WordPress', 'Wix', 'Squarespace', 'Webflow', 'Drupal', 'Joomla')
GROUP BY tech ORDER BY sites DESC;
Saída real da amostra de 10 000 linhas, obtida em 16/10/2026
kayorashop.store2026-10-11
moonovaactivewearshop.com2026-10-10
shopcastava.com2026-10-01
Registados nos últimos 30 dias, com o registrar. Substitua shop pelo nome da sua marca.
Mostrar a consulta
SELECT "Domain creation date"[:10] AS created, Domain, Registrar
FROM read_json('rdap-whois-2026-10-16.jsonl.zst', columns = {Domain: 'VARCHAR',
"Domain creation date": 'VARCHAR', Registrar: 'VARCHAR'})
WHERE Domain LIKE '%shop%'
AND "Domain creation date" >= CAST(current_date - 30 AS VARCHAR)
ORDER BY created DESC;
Que websites com classificação expiram nos próximos 30 dias?
Saída real da amostra de 10 000 linhas, obtida em 16/10/2026
adamcadre.ac2026-10-24
ama.ab.ca2026-10-31
psychologistsassociation.ab.ca2026-11-09
Ordenados por PR value. Muitas entidades de registo renovam automaticamente, por isso trate o resultado como uma lista de vigilância e não como uma lista de drops.
Mostrar a consulta
SELECT Domain, "Domain expiration date"[:10] AS expires
FROM read_json('websites-ranking-2026-10-16.jsonl.zst', columns = {Domain: 'VARCHAR',
"Domain expiration date": 'VARCHAR', "PR value": 'DOUBLE'})
WHERE "Domain expiration date"
BETWEEN CAST(current_date AS VARCHAR) AND CAST(current_date + 30 AS VARCHAR)
ORDER BY "PR value" DESC LIMIT 3;
Percentagem de domínios com um registo NS utilizável, agrupados pelos dois últimos rótulos do nome de anfitrião.
Mostrar a consulta
CREATE OR REPLACE MACRO provider(h) AS
array_to_string(string_split(lower(rtrim(h, '.')), '.')[-2:], '.');
SELECT provider(json_extract_string("DNS records", '$.NS[0]')) AS dns,
count(*) AS domains, round(100 * count(*) / sum(count(*)) OVER (), 1) AS pct
FROM read_json('dns-2026-10-16.jsonl.zst', columns = {"DNS records": 'JSON'})
WHERE dns <> '' GROUP BY dns ORDER BY domains DESC, dns LIMIT 3;
Criar uma lista a partir do ficheiro completo ou de um corte
O ficheiro completo não cabe numa folha de cálculo, por isso filtre-o primeiro ou comece por um corte: uma tecnologia, TLD, sufixo de TLD ou país como ficheiro próprio, a partir da respetiva página da webatla ou da API. Com acesso a Technologies ou a All data, cada página de tecnologia tem uma caixa de transferência para o seu corte.
A partir do ficheiro completo
Um TLD ou um sufixo
jq
O TLD é o último rótulo do domínio. O sufixo de TLD é o sufixo público exato.
# every domain under one TLD (de covers every suffix that ends in .de)
zstd -dc all-data-2026-10-16.jsonl.zst | jq -c 'select(.TLD == "de")' > de.jsonl
# exactly one suffix
zstd -dc all-data-2026-10-16.jsonl.zst | jq -c 'select(."TLD suffix" == "2ix.de")' > 2ix.de.jsonl
# a suffix that equals its TLD (com, de, ac) has no file of its own:
# filter the TLD slice instead
zstd -dc webatla-all-data-ac-2026-10-16.jsonl.zst | jq -c 'select(."TLD suffix" == "ac")' > ac.jsonl
Um website é uma linha com um endereço IP, e o seu país é onde o servidor está alojado (um código ISO em maiúsculas). O grep elimina as linhas que não podem corresponder e depois o jq verifica as restantes com exatidão.
zstd -dc all-data-2026-10-16.jsonl.zst \
| grep -F '"Country by IP":"DE"' \
| jq -c 'select(."IP address" != null and ."Country by IP" == "DE")' > de-websites.jsonl
Saída real da amostra de 10 000 linhas
de-websites.jsonl: 595 lines, the same as jq alone
Exportar para CSV para o Excel ou o Google Sheets
jq
O Excel mostra no máximo 1 048 576 linhas, por isso filtre primeiro. Importe o CSV como UTF-8 (Data, From Text/CSV) para que os nomes com caracteres não latinos apareçam corretamente.
COPY (
SELECT Domain AS Website, "Country by IP" AS Country
FROM read_json('webatla-technologies-WooCommerce-2026-10-16.jsonl.zst',
columns = {'Domain': 'VARCHAR', 'Country by IP': 'VARCHAR', 'PR value': 'DOUBLE'})
WHERE "Country by IP" = 'DE'
ORDER BY "PR value" DESC
) TO 'woocommerce-germany.csv';
Lista de upsell: sites HubSpot que também usam WordPress
O corte HubSpot e depois só os stacks com WordPress.
COPY (
SELECT Domain AS Website, "Country by IP" AS Country
FROM read_json('webatla-technologies-HubSpot-2026-10-16.jsonl.zst', columns = {
'Domain': 'VARCHAR', 'Country by IP': 'VARCHAR', 'Technologies': 'JSON'})
WHERE list_contains(CASE json_type(Technologies) WHEN 'OBJECT' THEN json_keys(Technologies)
ELSE json_extract_string(Technologies, '$[*]') END, 'WordPress')
) TO 'hubspot-on-wordpress.csv';
Saída real da amostra de 10 000 linhas
Website,Country
ateliercrescendo.ac,US
Operações de vendas
Um ficheiro por território
Divida um corte num CSV por país do servidor.
COPY (
SELECT Domain AS Website, coalesce("Country by IP", 'unknown') AS Country
FROM read_json('webatla-technologies-WooCommerce-2026-10-16.jsonl.zst',
columns = {'Domain': 'VARCHAR', 'Country by IP': 'VARCHAR'})
) TO 'woocommerce-by-country'
(FORMAT csv, PARTITION_BY (Country), WRITE_PARTITION_COLUMNS true, OVERWRITE);
Cabe numa folha de cálculo?Uma folha do Excel comporta 1 048 576 linhas
Sites com HubSpot375 063Cabe numa folha
Sites com WordPress23 798 524Filtrar ou dividir
All data, o ficheiro completo420 933 308Não cabe em nenhuma folha
5 · Carregá-lo
Postgres, Parquet ou um cruzamento com a sua própria lista
PostgreSQL
psql
Cada linha do ficheiro passa a ser uma linha jsonb, com um índice GIN em Technologies.
psql -c 'CREATE TABLE domains (doc jsonb)'
zstdcat technologies-2026-10-16.jsonl.zst \
| psql -c "\copy domains FROM STDIN WITH (FORMAT csv, QUOTE e'\x01', DELIMITER e'\x02')"
psql -c "CREATE INDEX ON domains USING gin ((doc->'Technologies'))"
psql -c "SELECT doc->>'Country by IP' AS country, count(*) AS sites FROM domains
WHERE doc->'Technologies' ? 'WordPress' GROUP BY 1 ORDER BY 2 DESC, 1 LIMIT 5"
Saída real da amostra de 10 000 linhas
COPY 10000
country | sites
---------+-------
US | 300
DE | 110
CA | 29
Parquet
DuckDB
Colunas tipadas, com Technologies como lista de nomes. Pode ser carregado em BigQuery, Snowflake, Spark ou pandas.
CREATE OR REPLACE MACRO techs(t) AS CASE json_type(t) WHEN 'OBJECT'
THEN json_keys(t) WHEN 'ARRAY' THEN t->>'$[*]' ELSE []::VARCHAR[] END;
COPY (SELECT "Domain" AS domain, "Country by IP" AS country,
"PR value" AS pr_value, techs("Technologies") AS technologies
FROM read_json('technologies-2026-10-16.jsonl.zst', columns = {
'Domain': 'VARCHAR', 'Country by IP': 'VARCHAR',
'PR value': 'DOUBLE', 'Technologies': 'JSON'}))
TO 'technologies.parquet' (FORMAT parquet);
Saída real da amostra de 10 000 linhas
technologies.parquet: 10000 rows
domain · country · pr_value · technologies (list of names)
Enriqueça a sua própria lista
DuckDB
O seu CSV de um lado, a exportação do outro, cruzados por Domain.
SELECT c.domain, w."Country by IP" AS country, w."Registrar" AS registrar,
w."HTTP status" AS http, w."Domain creation date"[:10] AS created
FROM read_csv('my-domains.csv') c
LEFT JOIN read_json('all-data-2026-10-16.jsonl.zst', columns = {
'Domain': 'VARCHAR', 'Country by IP': 'VARCHAR', 'Registrar': 'VARCHAR',
'HTTP status': 'INTEGER', 'Domain creation date': 'VARCHAR'}) w
ON w."Domain" = lower(trim(c.domain))
ORDER BY 1;
Saída real da amostra de 10 000 linhas
domain country registrar http created
Tamm.AbuDhabi AE ADSIC Registry Operator 200 2018-07-09
easy.ac US MarkMonitor Inc. 200 2014-02-27
global.abb US CSC Corporate Domains, Inc. 301 2019-10-03
6 · Atualizações diárias
Veja o que mudou de um dia para o outro
Todos os dias chega uma nova exportação. Compare dois dias por Domain e envie apenas as alterações para os seus sistemas a jusante. Troque a ordem dos dois ficheiros para listar os domínios que saíram.
COPY (
SELECT "Domain" FROM read_json('all-active-domains-2026-10-16.jsonl.zst',
columns = {'Domain': 'VARCHAR'})
EXCEPT
SELECT "Domain" FROM read_json('all-active-domains-2026-10-15.jsonl.zst',
columns = {'Domain': 'VARCHAR'})
) TO 'new-since-yesterday.csv' (HEADER false);
7 · Erros comuns
Onde é fácil tropeçar
Os nomes dos campos têm espaços
Coloque-os entre aspas, tanto em SQL como em jq.
jq: ."TLD suffix"SQL: "TLD suffix" = 'com.sa'
DNS Status é texto
Contém o texto "TRUE" ou "FALSE", não um booleano, por isso compare-o como texto.
select(."DNS Status" == "TRUE")
Technologies tem várias formas
Um mapa de nomes para versões (ou para objetos com uma versão), uma lista de nomes ou null. Leia as chaves de um mapa e os itens de uma lista e obterá sempre uma única lista.
jq: (.Technologies // []) | if type == "object" then keys else . end
Nunca descomprima um ficheiro completo para o disco
O ficheiro All data completo tem cerca de 34 GB comprimido e várias centenas de GB descomprimido. Leia-o em fluxo, como todas as receitas aqui.
Verifique as primeiras linhas
No DuckDB, um nome de coluna mal escrito devolve NULL e não um erro.
8 · Resolução de problemas
Quando algo corre mal
Sintoma
Causa e solução
zstd: … unsupported format na amostra gratuita
A amostra é JSONL simples, sem compressão. Passe-a diretamente ao jq ou use o zstdcat, que lê ambos.
O Python devolve muito menos linhas do que zstd -dc FILE | wc -l
O ficheiro tem vários frames zstd e foi lido com uma chamada que termina depois do primeiro. Use stream_reader com read_across_frames=True, como na receita Python.
jq: syntax error em .TLD suffix
Ponha entre aspas os nomes que contêm espaços: ."TLD suffix"
O SQL devolve 0 linhas sem erro
'Country by IP' entre aspas simples é um texto, não uma coluna. Use aspas duplas para nomes de colunas.
O DuckDB falha a meio com Expected OBJECT, but got ARRAY
A deteção automática do esquema olha apenas para as primeiras linhas. Declare as colunas, com os campos aninhados como JSON.
O ficheiro descarregado está completo?
zstd -tq FILE && echo OK apresenta OK quando o ficheiro descomprime por completo.
Todas as receitas funcionam no ficheiro diário completo
Acesso mensal ou anual, uma nova exportação todos os dias e uma API para cortes. Qualquer conta pode ainda descarregar uma amostra gratuita de 10 000 linhas de cada dataset.
Utilizamos cookies
Utilizamos cookies essenciais para manter o site a funcionar e cookies de análise opcionais para saber o que é útil.
Consulte a nossa política de privacidade.