A previsão do tempo é um daqueles blocos que elevam o valor de um site sem fazer barulho: o usuário passa mais tempo na página, volta com mais frequência e o conteúdo é percebido como «vivo». Por isso os widgets e blocos meteorológicos são tão frequentes nos portais urbanos e turísticos, nos serviços de reservas e nos sites de imóveis no exterior. Neste artigo, repassamos de onde obter dados meteorológicos, quais APIs são populares em 2026, em que o parsing de HTML difere do trabalho por meio de uma API, e mostramos implementações prontas em Python, JavaScript, PHP e Go.
O que é o «scraping do tempo» e que abordagens existem
Sob o rótulo de «scraping do tempo» costumam se agrupar duas tarefas de natureza distinta:
- Trabalhar por meio de uma API oficial. O serviço entrega dados estruturados (quase sempre JSON): dispara-se uma requisição HTTP e recebem-se campos prontos — temperatura, umidade, velocidade do vento, código do fenômeno meteorológico. É a via confiável, legal e previsível.
- Scraping de páginas HTML. Quando a fonte não oferece API ou ela é paga, os desenvolvedores extraem os dados diretamente do markup do site. Funciona, mas é frágil: qualquer mudança no HTML quebra o scraper, e a própria abordagem viola com frequência as condições de uso da fonte.
A conclusão prática é simples: sempre que existir uma API, use a API. Reserve o scraping para quando realmente não houver outra fonte e, em todo caso, verifique o robots.txt e as condições de uso.
Fontes de dados e APIs populares
Open-Meteo: gratuito e sem chave
O Open-Meteo é uma das opções mais convenientes para começar. A API não exige chave para uso não comercial, devolve os dados em JSON e agrega as previsões dos serviços meteorológicos nacionais com resolução de 1 a 11 km. Para projetos comerciais existem planos pagos à parte, com limites mensais de requisições. Ideal para protótipos, widgets e projetos open source.
OpenWeatherMap: o clássico com um limite gratuito amplo
O OpenWeatherMap segue sendo o serviço mais repetido nos tutoriais. Em 2026, conserva uma via gratuita operacional, mas importa entender qual produto exato está sendo chamado. Os endpoints clássicos (tempo atual, previsão a cada 3 horas, poluição do ar, mapas meteorológicos, geocodificação) estão disponíveis de graça com um limite de 60 requisições por minuto e até 1 000 000 de requisições por mês. Os produtos da família One Call (3.0 / 4.0) são assinaturas à parte, com cobrança por chamada e as primeiras 1000 requisições diárias gratuitas. Antes de ir para produção, vale definir um teto de gasto para não ultrapassar por acidente o limite gratuito.
WeatherAPI.com: um plano gratuito generoso
O WeatherAPI.com serve o tempo atual, a previsão horária e diária, dados históricos, astronomia e geolocalização, em JSON e XML. Uma escolha conveniente quando se busca um único provedor «para tudo» com um limite gratuito claro.
Visual Crossing: dados históricos potentes
O Visual Crossing é citado com frequência entre os melhores em relação custo-benefício: uma única API para o tempo atual, as previsões, os alertas e, sobretudo, séries históricas longas. Há chave gratuita e um Query Builder para montar consultas com exportação para JSON ou CSV. Boa opção para análise de dados e dashboards.
Plataformas para empresas: Tomorrow.io, Weatherbit, Meteomatics, meteoblue
Se forem necessários parâmetros muito especializados (cerca de 500 no Tomorrow.io, mais de 1800 no Meteomatics, séries históricas desde 1940), olhe para as plataformas corporativas. Elas oferecem alta precisão e um leque enorme de parâmetros, mas quase sempre exigem assinatura paga para uso comercial.
A fonte oficial do Brasil: INMET
O INMET, Instituto Nacional de Meteorologia, é o serviço meteorológico oficial do Brasil, e seu portal de dados abertos é a referência para projetos focados no país. O instituto mantém uma rede de centenas de estações meteorológicas automáticas e convencionais em todo o território e publica gratuitamente observações das estações, previsões por município, alertas e longas séries climatológicas.
Uma particularidade que vale conhecer: boa parte do acervo histórico é distribuída como arquivos CSV organizados por estação e por período — um formato pensado para download e análise, não para consultas pontuais. As estações são identificadas por códigos próprios, e os municípios seguem a codificação do IBGE. Os dados são reutilizáveis com citação do INMET como fonte, nas condições habituais dos dados abertos.
Serviços estatais e oficiais
Para os Estados Unidos existe a API gratuita e sem chave do Serviço Meteorológico Nacional (NWS, weather.gov): uma opção excelente para projetos civis e comunitários dentro do país. No Brasil, esse papel cabe ao INMET, com seu portal de dados abertos descrito acima, e os serviços meteorológicos nacionais de outros países mantêm portais de dados abertos semelhantes. As fontes estatais são gratuitas e confiáveis, mas costumam se limitar a um território específico.
Comparação por critérios-chave
| Fonte | Chave | Plano gratuito | Cobertura | Ideal para |
|---|---|---|---|---|
| Open-Meteo | Não exige (não comercial) | Sim, generoso | Global | Protótipos, widgets, open source |
| OpenWeatherMap | Exigida | Sim (endpoints clássicos) | Global | Tarefas universais |
| WeatherAPI.com | Exigida | Sim | Global | «Tudo em um» |
| Visual Crossing | Exigida | Sim | Global | Histórico, análise de dados |
| Tomorrow.io / Meteomatics | Exigida | Teste/limite | Global | Negócios, parâmetros específicos |
| INMET (dados abertos) | Não exige (dados abertos) | Sim (dados abertos) | Brasil | Projetos focados no Brasil |
| NWS (weather.gov) | Não exige | Sim | Somente EUA | Projetos civis nos EUA |
Implementações em várias linguagens
Em todos os exemplos a seguir, usa-se o Open-Meteo, porque não precisa de chave: o código pode ser executado como está. As coordenadas dos exemplos correspondem a São Paulo (-23.55, -46.63). Para migrar a outro provedor, costuma bastar trocar a URL, adicionar a chave e ajustar o parsing do JSON.
Python (requests)
import requests
def get_weather(lat: float, lon: float) -> dict:
url = "https://api.open-meteo.com/v1/forecast"
params = {
"latitude": lat,
"longitude": lon,
"current": "temperature_2m,relative_humidity_2m,wind_speed_10m,weather_code",
"timezone": "auto",
}
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
return response.json()
data = get_weather(-23.55, -46.63)
current = data["current"]
print(f"Temperatura: {current['temperature_2m']}°C")
print(f"Umidade: {current['relative_humidity_2m']}%")
print(f"Vento: {current['wind_speed_10m']} km/h")Versão para o OpenWeatherMap com chave e localização em português:
import requests
API_KEY = "SUA_CHAVE"
def get_weather_owm(city: str) -> dict:
url = "https://api.openweathermap.org/data/2.5/weather"
params = {"q": city, "units": "metric", "lang": "pt_br", "appid": API_KEY}
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
d = response.json()
return {
"cidade": d["name"],
"temperatura": d["main"]["temp"],
"sensacao": d["main"]["feels_like"],
"descricao": d["weather"][0]["description"],
}
print(get_weather_owm("São Paulo"))JavaScript / Node.js (fetch nativo)
No Node.js 18+, o fetch já vem disponível por padrão: não é preciso instalar dependências externas.
async function getWeather(lat, lon) {
const url = new URL("https://api.open-meteo.com/v1/forecast");
url.searchParams.set("latitude", lat);
url.searchParams.set("longitude", lon);
url.searchParams.set("current", "temperature_2m,wind_speed_10m,weather_code");
url.searchParams.set("timezone", "auto");
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Erro HTTP: ${response.status}`);
}
return response.json();
}
getWeather(-23.55, -46.63)
.then((data) => {
const c = data.current;
console.log(`Temperatura: ${c.temperature_2m}°C, vento: ${c.wind_speed_10m} km/h`);
})
.catch((err) => console.error("Não foi possível obter os dados do tempo:", err.message));PHP (cURL)
<?php
function getWeather(float $lat, float $lon): ?array
{
$query = http_build_query([
'latitude' => $lat,
'longitude' => $lon,
'current' => 'temperature_2m,wind_speed_10m,weather_code',
'timezone' => 'auto',
]);
$url = "https://api.open-meteo.com/v1/forecast?{$query}";
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_USERAGENT => 'WeatherWidget/1.0',
]);
$body = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($body === false || $code !== 200) {
return null;
}
return json_decode($body, true);
}
$data = getWeather(-23.55, -46.63);
if ($data !== null) {
echo "Temperatura: " . $data['current']['temperature_2m'] . "°C\n";
}Go
package main
import (
"encoding/json"
"fmt"
"net/http"
"time"
)
type WeatherResponse struct {
Current struct {
Temperature float64 `json:"temperature_2m"`
WindSpeed float64 `json:"wind_speed_10m"`
WeatherCode int `json:"weather_code"`
} `json:"current"`
}
func main() {
url := "https://api.open-meteo.com/v1/forecast" +
"?latitude=-23.55&longitude=-46.63" +
"¤t=temperature_2m,wind_speed_10m,weather_code&timezone=auto"
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Get(url)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var data WeatherResponse
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
panic(err)
}
fmt.Printf("Temperatura: %.1f°C, vento: %.1f km/h\n",
data.Current.Temperature, data.Current.WindSpeed)
}Dados históricos do INMET (medições das estações automáticas)
# Localize no portal de dados abertos do INMET o conjunto desejado
# (por exemplo, o arquivo anual com as medições das estações automáticas)
# e baixe o CSV compactado a partir da URL indicada no portal
curl -O "URL_DO_ARQUIVO_NO_PORTAL"Cada arquivo reúne as medições de uma estação (temperatura, umidade, vento, precipitação) em intervalos horários; as previsões por município usam os códigos do IBGE. Antes de ir para produção, confira os endpoints e os formatos na documentação oficial do portal.
O scraping de HTML como plano B (Python + BeautifulSoup)
Quando não há API disponível, os dados podem ser extraídos do markup. A abordagem funciona, mas é frágil: se o HTML muda, os seletores deixam de servir, e só é admissível usá-la se não contrariar as condições da fonte.
import requests
from bs4 import BeautifulSoup
def scrape_weather(url: str) -> str:
headers = {"User-Agent": "Mozilla/5.0"}
html = requests.get(url, headers=headers, timeout=10).text
soup = BeautifulSoup(html, "html.parser")
# O seletor é ajustado à página de origem específica
temp = soup.select_one(".temperature")
return temp.get_text(strip=True) if temp else "não encontrado"A decodificação do
weather_codeno Open-Meteo segue o padrão da WMO: por exemplo, 0 — céu limpo, 2 — nebulosidade variável, 61 — chuva fraca, 71 — neve fraca. Mantenha a tabela completa de códigos como um dicionário de mapeamento para exibir ao usuário uma descrição legível.
Cache, limites e questões legais
Algumas regras que economizam dinheiro e dores de cabeça em produção:
- Faça cache das respostas. O tempo quase nunca precisa ser atualizado a cada visualização de página. Faça cache por coordenadas, cidade ou CEP e renove as condições atuais a cada 5--15 minutos. Nos aplicativos móveis, encaminhe as requisições pelo seu próprio backend em vez de dispará-las de cada cliente.
- Guarde as chaves no servidor. A chave de API não deve ser embutida no código cliente: é fácil roubá-la. As requisições devem passar pelo seu proxy de backend.
- Monitore os limites. Configure o tratamento das respostas 401 (chave incorreta) e 429 (limite excedido) e alertas para um crescimento brusco no número de chamadas.
- Verifique a licença. A maioria dos planos gratuitos só permite uso não comercial. Alguns serviços (Visual Crossing, OpenWeatherMap) admitem uso comercial limitado com citação da fonte. Para o scraping, revise sempre o
robots.txte as condições de uso.
Onde se aplica: portais, turismo e imobiliário
Um bloco meteorológico é o complemento típico dos projetos ligados à geografia e ao estilo de vida do usuário:
- Os portais urbanos mostram o tempo atual e a previsão na página inicial: isso retém a audiência e transforma o site em um ponto de entrada diário.
- Os portais turísticos e os serviços de reservas adicionam o tempo à página do destino: para o viajante, importa saber o que o espera na chegada.
- Os sites de imóveis no exterior usam o tempo como parte da «venda do clima»: dias ensolarados, invernos suaves e temperaturas agradáveis são um argumento de peso na escolha de um imóvel à beira-mar ou na montanha.
O curioso é que, tecnicamente, o scraping do tempo pertence à mesma família de outra tarefa popular desses projetos: a coleta e agregação de anúncios. Se o tempo faz a página do destino parecer «viva», preencher o catálogo de imóveis é tarefa do scraping imobiliário: coleta automática de ofertas nos portais de origem, normalização de preços e características, atualização da base. Muitas vezes os dois módulos trabalham lado a lado: um cuida do conteúdo do imóvel e o outro, do contexto que o cerca.
Conclusão
Para a maioria das tarefas, o sensato é começar pelo Open-Meteo (início imediato, sem chave) ou pelo OpenWeatherMap (limite gratuito amplo e um ecossistema maduro). Se os dados históricos pesam, olhe para o Visual Crossing; se o projeto é focado no Brasil, a fonte oficial é o INMET. Tecnicamente, a integração ocupa poucas linhas em qualquer linguagem: requisição HTTP, parsing do JSON, cache. E um bloco do tempo bem integrado eleva de forma notável o engajamento nos portais urbanos, turísticos e imobiliários — ali onde ao usuário importa não só o objeto em si, mas também o contexto que o cerca.