CNPJfy
Documentação Técnica

API OpenCNPJ

Documentação completa da API pública para consulta de dados empresariais brasileiros. Gratuita, rápida e sem necessidade de autenticação.

Quick Start

URL Base

https://opencnpj.com/api

Autenticação

Não requer autenticação
Completamente gratuita
Rate limit: 50 req/s

📡 Endpoints Disponíveis

GET
/{cnpj}

Consultar Empresa por CNPJ

Retorna informações completas de uma empresa brasileira através do seu CNPJ.

Parâmetros

ParâmetroTipoObrigatórioDescrição
cnpjstringSimCNPJ da empresa (com ou sem formatação). Deve conter 14 dígitos.

Exemplo de Requisição

curl -X GET "https://opencnpj.com/api/11222333000181" \
  -H "Accept: application/json"

Exemplo de Resposta (200 OK)

{
  "cnpj": "11.222.333/0001-81",
  "identificador_matriz_filial": 1,
  "descricao_matriz_filial": "MATRIZ",
  "razao_social": "EMPRESA EXEMPLO LTDA",
  "nome_fantasia": "EXEMPLO",
  "situacao_cadastral": 2,
  "descricao_situacao_cadastral": "ATIVA",
  "data_situacao_cadastral": "2020-01-15",
  "motivo_situacao_cadastral": 0,
  "nome_cidade_exterior": null,
  "codigo_natureza_juridica": 2062,
  "data_inicio_atividade": "2020-01-15",
  "cnae_fiscal": 6201500,
  "cnae_fiscal_descricao": "Desenvolvimento de programas de computador sob encomenda",
  "descricao_tipo_logradouro": "RUA",
  "logradouro": "DAS FLORES",
  "numero": "123",
  "complemento": "SALA 456",
  "bairro": "CENTRO",
  "cep": "01234567",
  "uf": "SP",
  "codigo_municipio": 7107,
  "municipio": "SAO PAULO",
  "ddd_telefone_1": "11987654321",
  "ddd_telefone_2": null,
  "ddd_fax": null,
  "qualificacao_do_responsavel": 10,
  "capital_social": 50000.00,
  "porte": "05",
  "descricao_porte": "DEMAIS",
  "opcao_pelo_simples": true,
  "data_opcao_pelo_simples": "2020-02-01",
  "data_exclusao_do_simples": null,
  "opcao_pelo_mei": false,
  "situacao_especial": null,
  "data_situacao_especial": null
}
GET
/info

Informações da Base de Dados

Retorna informações sobre a base de dados, incluindo data da última atualização e estatísticas.

Exemplo de Requisição

curl -X GET "https://opencnpj.com/api/info" \
  -H "Accept: application/json"

Exemplo de Resposta (200 OK)

{
  "ultima_atualizacao": "2024-01-15T10:30:00Z",
  "total_empresas": 54789123,
  "empresas_ativas": 45123789,
  "versao_base": "2024.01",
  "fonte": "Receita Federal do Brasil",
  "status": "online"
}

📊 Códigos de Status HTTP

CódigoStatusDescriçãoPossíveis Causas
200SucessoEmpresa encontrada e dados retornadosRequisição válida com CNPJ existente
400Requisição InválidaParâmetros inválidos ou malformadosCNPJ com formato inválido ou ausente
404Não EncontradoCNPJ não encontrado na base de dadosCNPJ não existe ou não está ativo
429Muitas RequisiçõesRate limit excedidoMais de 50 requisições por segundo
500Erro Interno do ServidorErro interno temporárioProblema temporário no servidor
503Service UnavailableServiço temporariamente indisponívelManutenção programada ou sobrecarga

💻 Exemplos de Implementação

JavaScript

Usando fetch (nativo)

async function consultarCNPJ(cnpj) {
  try {
    const response = await fetch(`https://opencnpj.com/api/${cnpj}`, {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
        'User-Agent': 'MeuApp/1.0'
      }
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const empresa = await response.json();
    console.log('Empresa encontrada:', empresa);
    return empresa;
  } catch (error) {
    console.error('Erro ao consultar CNPJ:', error);
    throw error;
  }
}

// Uso
consultarCNPJ('11222333000181')
  .then(empresa => {
    console.log(`Razão Social: ${empresa.razao_social}`);
    console.log(`CNAE: ${empresa.cnae_fiscal_descricao}`);
  })
  .catch(error => {
    console.error('Falha na consulta:', error);
  });

Usando axios

const axios = require('axios');

// Configuração do cliente
const apiClient = axios.create({
  baseURL: 'https://opencnpj.com/api',
  timeout: 30000,
  headers: {
    'Accept': 'application/json',
    'User-Agent': 'MeuApp/1.0'
  }
});

// Interceptor para retry automático
apiClient.interceptors.response.use(
  response => response,
  async error => {
    if (error.response?.status === 429) {
      await new Promise(resolve => setTimeout(resolve, 2000));
      return apiClient.request(error.config);
    }
    return Promise.reject(error);
  }
);

async function consultarCNPJ(cnpj) {
  try {
    const response = await apiClient.get(`/${cnpj}`);
    return response.data;
  } catch (error) {
    if (error.response?.status === 404) {
      throw new Error('CNPJ não encontrado');
    } else if (error.response?.status === 400) {
      throw new Error('CNPJ inválido');
    } else {
      throw new Error('Erro na consulta: ' + error.message);
    }
  }
}

// Uso
consultarCNPJ('11222333000181')
  .then(empresa => {
    console.log(`Empresa: ${empresa.razao_social}`);
  })
  .catch(error => {
    console.error(error.message);
  });

🐍Python

Implementação completa com requests

import requests
import time
from typing import Optional, Dict, Any

class OpenCNPJClient:
    def __init__(self, base_url: str = "https://opencnpj.com/api"):
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({
            'Accept': 'application/json',
            'User-Agent': 'MeuApp/1.0'
        })
        self.session.timeout = 30

    def consultar_cnpj(self, cnpj: str) -> Optional[Dict[str, Any]]:
        """
        Consulta informações de uma empresa pelo CNPJ
        
        Args:
            cnpj (str): CNPJ da empresa (com ou sem formatação)
            
        Returns:
            Dict com informações da empresa ou None se não encontrada
            
        Raises:
            ValueError: Se o CNPJ for inválido
            requests.RequestException: Se houver erro na requisição
        """
        # Remove formatação do CNPJ
        cnpj_limpo = ''.join(filter(str.isdigit, cnpj))
        
        if not self.validar_cnpj(cnpj_limpo):
            raise ValueError("CNPJ inválido")
        
        url = f"{self.base_url}/{cnpj_limpo}"
        
        try:
            response = self.session.get(url)
            
            if response.status_code == 200:
                return response.json()
            elif response.status_code == 404:
                return None
            elif response.status_code == 429:
                # Rate limit - aguarda e tenta novamente
                time.sleep(2)
                response = self.session.get(url)
                if response.status_code == 200:
                    return response.json()
                else:
                    response.raise_for_status()
            else:
                response.raise_for_status()
                
        except requests.RequestException as e:
            raise requests.RequestException(f"Erro na consulta: {e}")

    def obter_info(self) -> Dict[str, Any]:
        """Obtém informações sobre a base de dados"""
        url = f"{self.base_url}/info"
        response = self.session.get(url)
        response.raise_for_status()
        return response.json()

    def validar_cnpj(self, cnpj: str) -> bool:
        """Valida se o CNPJ possui formato correto"""
        return len(cnpj) == 14 and cnpj.isdigit()

# Exemplo de uso
if __name__ == "__main__":
    client = OpenCNPJClient()
    
    try:
        # Consultar empresa
        empresa = client.consultar_cnpj("11.222.333/0001-81")
        
        if empresa:
            print(f"Razão Social: {empresa['razao_social']}")
            print(f"CNAE: {empresa['cnae_fiscal_descricao']}")
            print(f"Situação: {empresa['descricao_situacao_cadastral']}")
        else:
            print("Empresa não encontrada")
            
        # Obter informações da base
        info = client.obter_info()
        print(f"Última atualização: {info['ultima_atualizacao']}")
        
    except ValueError as e:
        print(f"Erro de validação: {e}")
    except requests.RequestException as e:
        print(f"Erro na requisição: {e}")

Java

Implementação com HttpClient (Java 11+)

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class OpenCNPJClient {
    private final HttpClient httpClient;
    private final ObjectMapper objectMapper;
    private final String baseUrl;

    public OpenCNPJClient() {
        this.baseUrl = "https://opencnpj.com/api";
        this.httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(30))
            .build();
        this.objectMapper = new ObjectMapper();
    }

    public JsonNode consultarCNPJ(String cnpj) throws Exception {
        // Remove formatação do CNPJ
        String cnpjLimpo = cnpj.replaceAll("[^0-9]", "");
        
        if (!validarCNPJ(cnpjLimpo)) {
            throw new IllegalArgumentException("CNPJ inválido");
        }

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/" + cnpjLimpo))
            .header("Accept", "application/json")
            .header("User-Agent", "MeuApp/1.0")
            .timeout(Duration.ofSeconds(30))
            .GET()
            .build();

        try {
            HttpResponse<String> response = httpClient.send(request,
                HttpResponse.BodyHandlers.ofString());

            switch (response.statusCode()) {
                case 200:
                    return objectMapper.readTree(response.body());
                case 404:
                    return null;
                case 429:
                    // Rate limit - aguarda e tenta novamente
                    Thread.sleep(2000);
                    HttpResponse<String> retryResponse = httpClient.send(request,
                        HttpResponse.BodyHandlers.ofString());
                    if (retryResponse.statusCode() == 200) {
                        return objectMapper.readTree(retryResponse.body());
                    }
                    throw new RuntimeException("Rate limit excedido");
                default:
                    throw new RuntimeException("Erro HTTP: " + response.statusCode());
            }
        } catch (Exception e) {
            throw new Exception("Erro na consulta: " + e.getMessage(), e);
        }
    }

    public CompletableFuture<JsonNode> consultarCNPJAsync(String cnpj) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return consultarCNPJ(cnpj);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    public JsonNode obterInfo() throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/info"))
            .header("Accept", "application/json")
            .timeout(Duration.ofSeconds(30))
            .GET()
            .build();

        HttpResponse<String> response = httpClient.send(request,
            HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() == 200) {
            return objectMapper.readTree(response.body());
        } else {
            throw new RuntimeException("Erro HTTP: " + response.statusCode());
        }
    }

    private boolean validarCNPJ(String cnpj) {
        return cnpj != null && cnpj.length() == 14 && cnpj.matches("\\d+");
    }

    // Exemplo de uso
    public static void main(String[] args) {
        OpenCNPJClient client = new OpenCNPJClient();

        try {
            // Consulta síncrona
            JsonNode empresa = client.consultarCNPJ("11.222.333/0001-81");
            
            if (empresa != null) {
                System.out.println("Razão Social: " + 
                    empresa.get("razao_social").asText());
                System.out.println("CNAE: " + 
                    empresa.get("cnae_fiscal_descricao").asText());
                
                // Processar sócios (QSA)
                if (empresa.has("QSA") && empresa.get("QSA").isArray()) {
                    System.out.println("Sócios:");
                    empresa.get("QSA").forEach(socio -> {
                        System.out.println("- " + socio.get("nome").asText());
                    });
                }
            } else {
                System.out.println("Empresa não encontrada");
            }

            // Consulta assíncrona
            client.consultarCNPJAsync("11222333000181")
                .thenAccept(result -> {
                    if (result != null) {
                        System.out.println("Consulta assíncrona concluída");
                    }
                })
                .join();

        } catch (Exception e) {
            System.err.println("Erro: " + e.getMessage());
        }
    }
}

🔧 Guia de Integração

Boas Práticas

  • Implemente cache local para evitar requisições desnecessárias
  • Valide o CNPJ antes de fazer a requisição
  • Trate todos os códigos de erro adequadamente
  • Use timeouts apropriados (30s recomendado)
  • Implemente retry com backoff exponencial
  • Monitore o rate limit através dos headers

Evite Fazer

  • Não faça mais de 50 requisições por segundo
  • Não ignore os códigos de erro HTTP
  • Não faça requisições paralelas excessivas
  • Não armazene dados por mais de 30 dias
  • Não use a API para scraping em massa
  • Não redistribua os dados sem autorização

⚖️ Limitações e Termos de Uso

Limitações Técnicas

  • Rate Limit: 50 requisições/segundo por IP
  • Timeout: 30 segundos por requisição
  • Dados: Atualizados mensalmente
  • Disponibilidade: 99.5% SLA (não garantido)
  • Cache: Recomendado cache local de 24h

Termos de Uso

  • Uso gratuito para fins legítimos
  • Proibido uso para spam ou atividades ilegais
  • Dados são públicos da Receita Federal
  • Sem garantias de disponibilidade
  • Respeite os limites de rate limiting

🤝 Suporte e Comunidade

Precisa de ajuda? Nossa comunidade está aqui para apoiar!