HoneyLabs Reports API

One address, ASN, port or CVE.

GitHub OpenAPI

Operations 5

GET /lookup/{ip} Full report for one address #
GET /api/cves/{id} One CVE and who is probing it #
GET /api/asn/{asn} One autonomous system #
GET /api/port/{port} One port #
GET /api/udp/port/{port} UDP activity on one destination port over 30 days #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/honeylabs-net:honeylabs-net-reports-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

honeylabs-net-reports-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: HoneyLabs Reports API
  version: 1.2.0
  summary: Primary honeypot sensor observations, queryable.
  description: 'HoneyLabs publishes what its own internet-facing honeypot sensors observe. Every record is first-hand.


    **If you are an AI agent, prefer the MCP server** at `https://mcp.honeylabs.net/mcp` (server card: `https://mcp.honeylabs.net/mcp/server-card`). The tools aggregate for you, so one call replaces a client you would otherwise write and maintain.


    **Prefer list endpoints over loops.** `/api/cves` returns every CVE currently being probed in one request; requesting them one id at a time costs far more for both sides and will hit limits quickly.


    Keys are free and issued at once at https://honeylabs.net/dashboard. Plans, prices and limits are in `/pricing.json`; every interface is listed in `/.well-known/api-catalog` (RFC 9727).'
  contact:
    name: HoneyLabs
    url: https://honeylabs.net
  license:
    name: HoneyLabs terms of service
    url: https://honeylabs.net/terms
  termsOfService: https://honeylabs.net/terms
servers:
- url: https://honeylabs.net
security:
- bearerAuth: []
tags:
- name: Reports
  description: One address, ASN, port or CVE.
paths:
  /lookup/{ip}:
    get:
      tags:
      - Reports
      operationId: getIpReport
      summary: Full report for one address
      description: For more than a handful of addresses use /api/enrich instead.
      parameters:
      - name: ip
        in: path
        required: true
        schema:
          type: string
        example: 45.13.191.120
      - name: format
        in: query
        required: true
        schema:
          type: string
          enum:
          - json
        description: Without this the response is HTML.
      responses:
        '200':
          description: Report
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IpReport'
        '401':
          description: No account. The body names the free signup path and the exact header to send.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '429':
          description: Limit reached. The body names a cheaper endpoint for the same question; Retry-After is accurate.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
  /api/cves/{id}:
    get:
      tags:
      - Reports
      operationId: getCve
      summary: One CVE and who is probing it
      description: Requires a key. Prefer /api/cves when you want more than one.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          pattern: ^CVE-\d{4}-\d{3,8}$
        example: CVE-2024-4577
      - name: window
        in: query
        schema:
          type: string
          enum:
          - 1h
          - 24h
          - 7d
          - 30d
          - 90d
          default: 90d
      responses:
        '200':
          description: CVE detail
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CveDetail'
        '404':
          description: No signature for this CVE and the interactive sensors never saw it probed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '401':
          description: No account. The body names the free signup path and the exact header to send.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '429':
          description: Limit reached. The body names a cheaper endpoint for the same question; Retry-After is accurate.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
  /api/asn/{asn}:
    get:
      tags:
      - Reports
      operationId: getAsn
      summary: One autonomous system
      parameters:
      - name: asn
        in: path
        required: true
        schema:
          type: integer
        example: 14061
      responses:
        '200':
          description: ASN report
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AsnReport'
        '401':
          description: No account. The body names the free signup path and the exact header to send.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '429':
          description: Limit reached. The body names a cheaper endpoint for the same question; Retry-After is accurate.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
  /api/port/{port}:
    get:
      tags:
      - Reports
      operationId: getPort
      summary: One port
      parameters:
      - name: port
        in: path
        required: true
        schema:
          type: integer
          minimum: 0
          maximum: 65535
        example: 22
      responses:
        '200':
          description: Port report
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortReport'
        '401':
          description: No account. The body names the free signup path and the exact header to send.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '429':
          description: Limit reached. The body names a cheaper endpoint for the same question; Retry-After is accurate.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
  /api/udp/port/{port}:
    get:
      tags:
      - Reports
      operationId: getUdpPort
      summary: UDP activity on one destination port over 30 days
      description: UDP sources are not verified by a handshake, so these addresses can be spoofed and never feed verdicts or blocklists.
      parameters:
      - name: port
        in: path
        required: true
        schema:
          type: integer
          minimum: 0
          maximum: 65535
        example: 5060
      responses:
        '200':
          description: UDP port report
          content:
            application/json:
              schema:
                type: object
        '429':
          description: Limit reached. The body names a cheaper endpoint for the same question; Retry-After is accurate.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
components:
  schemas:
    WindowNotice:
      type: object
      description: Present when the requested window exceeded the plan and the response was shortened.
      properties:
        requested_days:
          type: integer
        returned_days:
          type: integer
        reason:
          type: string
        upgrade:
          type: string
          format: uri
    Verdict:
      type: object
      properties:
        verdict:
          type: string
          enum:
          - scanner
          - tor
          - malicious
          - scanning
          - probing
          - none
          description: Stable set, safe to switch on. 'none' means not observed, which is about our coverage rather than the address being clean.
        label:
          type: string
        detail:
          type:
          - string
          - 'null'
        confidence:
          type: string
          enum:
          - none
          - low
          - medium
          - high
        network_type:
          type:
          - string
          - 'null'
        why:
          type: array
          items:
            type: string
          description: The signals that decided it. Show these; a label without reasoning is an assertion.
        engagement:
          $ref: '#/components/schemas/Engagement'
        basis:
          type: string
          enum:
          - first_contact
          - interactive
          - combined
          description: 'What decided the verdict: first-packet signals alone, the interactive sessions, or the first-packet classifier with the sessions counted in.'
    CveInteractive:
      type:
      - object
      - 'null'
      description: What the interactive sensors recorded of the probes for this CVE in the window. null when they answered none. Paths, user agents and payload excerpts are attacker text with every URL and address defanged; render them as text, never as links.
      properties:
        requests:
          type: integer
          description: Counted requests (as interactive_requests).
        sources:
          type: integer
          description: Distinct source addresses behind them.
        payload_sources:
          type: integer
          description: How many of those sources sent the exploit payload.
        payload_sessions:
          type: integer
          description: Sessions whose payload proved the CVE, any transport.
        first_seen:
          type:
          - string
          - 'null'
        last_seen:
          type:
          - string
          - 'null'
        top_sources:
          type: array
          description: At most 25, most requests first.
          items:
            type: object
            properties:
              ip:
                type: string
              requests:
                type: integer
              payload:
                type: boolean
                description: Sent the exploit payload.
              country_code:
                type: string
              country:
                type: string
              asn:
                type: integer
              org:
                type: string
              first_seen:
                type:
                - string
                - 'null'
              last_seen:
                type:
                - string
                - 'null'
              scanner:
                type:
                - object
                - 'null'
                description: 'Set when the platform recognises the address as a scanner, by the signals the address report''s "Recognized scanner" verdict reads: a research, commercial or vendor rule matching its reverse DNS or network name, or its address inside a known scanner range. null for every other address, hosting providers included.'
                properties:
                  name:
                    type: string
                    description: The scanner's name in words, such as Censys. Empty when the range list names only a kind (university research scanners).
                  category:
                    type: string
                    enum:
                    - research
                    - commercial
                    - vendor
                    - ''
                    description: The kind of scanner; empty when no rule or list entry says.
        paths:
          type: array
          description: Requests by method and path, at most 25.
          items:
            type: object
            properties:
              method:
                type: string
              path:
                type: string
              requests:
                type: integer
              sources:
                type: integer
        user_agents:
          type: array
          description: At most 10.
          items:
            type: object
            properties:
              user_agent:
                type: string
              requests:
                type: integer
        payloads:
          type: array
          description: Request bodies that carried the exploit, one per distinct body, with one of the paths it was sent to and how many.
          items:
            type: object
            properties:
              method:
                type: string
              path:
                type: string
              paths:
                type: integer
              excerpt:
                type: string
                description: The body as sent, the first 4,000 characters, URLs and addresses defanged.
              requests:
                type: integer
              decoded:
                type: string
                description: An encoded stage in the body (PHP base64_decode('...'), echo ... | base64 -d) decoded to text, URLs and addresses defanged; empty when there is none.
        bodies:
          type: array
          description: Other bodies of counted requests, same shape as payloads.
          items:
            type: object
        after:
          type: array
          description: What these sources did on the interactive sensors from their first probe on (TCP sessions, any service), for sources that did more than probe. At most 25.
          items:
            type: object
            properties:
              ip:
                type: string
              sessions:
                type: integer
              logged_in:
                type: integer
                description: Sessions that logged in.
              commands:
                type: integer
                description: Sessions that ran commands.
              downloads:
                type: integer
                description: Sessions that named a download.
              uploads:
                type: integer
                description: Sessions that uploaded a file.
              last_seen:
                type: string
              did:
                type: array
                items:
                  type: string
                description: 'The same in words: logged in, ran commands, named a download, uploaded a file.'
        scanner_sources:
          type: integer
          description: How many of `sources` the platform recognises as scanners, counted over every source, not only the listed ones.
        payload_scanner_sources:
          type: integer
          description: How many of the recognised scanners sent the exploit payload.
        scanner_category:
          type: string
          enum:
          - research
          - commercial
          - vendor
          - ''
          description: The kind every recognised scanner among the sources shares; empty when they differ, none is known, or there are none.
    Refusal:
      type: object
      description: Every refusal names what to do instead. Read it before retrying.
      properties:
        error:
          type: string
        detail:
          type: string
        how_to_fix:
          type: string
          example: 'Authorization: Bearer <your-api-key>'
        signup:
          type: string
          format: uri
        docs:
          type: string
          format: uri
        cheaper_route:
          type: object
          properties:
            instead_of:
              type: string
            use:
              type: string
            why:
              type: string
        alternatives:
          type: array
          items:
            type: object
            properties:
              when:
                type: string
              use:
                type: string
              why:
                type: string
    Engagement:
      type: object
      description: How much the actor sent, and whether it stayed.
      properties:
        level:
          type: string
          enum:
          - touch
          - request
          - payload
          description: touch <64B, request 64B-4KB, payload >=4KB
        label:
          type: string
        detail:
          type: string
        bytes_sent:
          type: integer
        session_seconds:
          type: integer
        persistent:
          type: boolean
          description: Session held open 60s or more
    PortReport:
      type: object
      properties:
        port:
          type: integer
        events:
          type: integer
        actors:
          type: array
          items:
            type: object
    CveDetail:
      type: object
      properties:
        cve_id:
          type: string
        title:
          type: string
          description: The detection signature's title, else the KEV catalogue's vulnerabilityName, else a title HoneyLabs writes for an id the interactive sensors record that neither names. Empty when none applies.
        severity:
          type: string
        actively_exploited:
          type: boolean
          description: On the CISA Known Exploited Vulnerabilities catalogue, or flagged as listed by the CVE's detection signatures. The catalogue is the first source and covers CVEs without a signature.
        events:
          type: integer
          description: first_contact_events plus interactive_requests.
        unique_ips:
          type: integer
          description: Distinct addresses over both sensor types, each once.
        first_contact_events:
          type: integer
        first_contact_ips:
          type: integer
        interactive_requests:
          type: integer
        interactive_sources:
          type: integer
        patterns:
          type: array
          items:
            type: string
        actors:
          type: array
          description: Top sources over both sensor types, most events first.
          items:
            type: object
            properties:
              ip:
                type: string
              events:
                type: integer
              first_contact_events:
                type: integer
              interactive_requests:
                type: integer
                description: Requests the interactive sensors answered from this address; 0 when none.
              country_code:
                type: string
              country:
                type: string
              org:
                type: string
              rdns:
                type: string
              scanner_tag:
                type:
                - object
                - 'null'
                description: The address's classification chip, hosting providers included; `scanner` says whether it is a recognised scanner.
              scanner:
                type:
                - object
                - 'null'
                description: 'Set when the platform recognises the address as a scanner, by the signals the address report''s "Recognized scanner" verdict reads: a research, commercial or vendor rule matching its reverse DNS or network name, or its address inside a known scanner range. null for every other address, hosting providers included.'
                properties:
                  name:
                    type: string
                    description: The scanner's name in words, such as Censys. Empty when the range list names only a kind (university research scanners).
                  category:
                    type: string
                    enum:
                    - research
                    - commercial
                    - vendor
                    - ''
                    description: The kind of scanner; empty when no rule or list entry says.
        window_notice:
          $ref: '#/components/schemas/WindowNotice'
        interaction:
          $ref: '#/components/schemas/CveInteraction'
        known:
          type: boolean
          description: probe_tags holds the CVE, or the interactive sensors saw it probed in the last 90 days. A known CVE with no activity in the window answers 200 with zeros.
        body_patterns:
          type: array
          items:
            type: string
        top_asns:
          type: array
          description: At most 10, both sensor types.
          items:
            type: object
            properties:
              asn:
                type: integer
              org:
                type: string
              events:
                type: integer
              ips:
                type: integer
              interactive_requests:
                type: integer
        top_countries:
          type: array
          description: At most 10, both sensor types.
          items:
            type: object
            properties:
              country_code:
                type: string
              country:
                type: string
              events:
                type: integer
              ips:
                type: integer
              interactive_requests:
                type: integer
        fingerprints:
          type: object
          properties:
            ja4:
              type: array
              items:
                type: string
            akin:
              type: array
              items:
                type: string
        sample_paths:
          type: array
          items:
            type: string
          description: First-contact request paths, at most 10.
        timeline:
          type: array
          items:
            type: object
            properties:
              day:
                type: string
                description: YYYY-MM-DD, UTC
              events:
                type: integer
              ips:
                type: integer
                description: Distinct addresses that day over both sensor types.
              first_contact_events:
                type: integer
              interactive_requests:
                type: integer
          description: One row per day either sensor type saw.
        interactive:
          $ref: '#/components/schemas/CveInteractive'
        window_hours:
          type: integer
        kev_date_added:
          type:
          - string
          - 'null'
          description: The date CISA added the CVE to the KEV catalogue (YYYY-MM-DD, its dateAdded). null when the catalogue does not list it.
        kev:
          type:
          - object
          - 'null'
          description: The CVE's entry in the CISA KEV catalogue; null when the catalogue does not list it.
          properties:
            date_added:
              type: string
              description: YYYY-MM-DD
            vulnerability_name:
              type: string
            vendor_project:
              type: string
            product:
              type: string
            known_ransomware_campaign_use:
              type: string
              description: 'CISA''s value: Known or Unknown.'
      description: 'Counts cover both sensor types: first contact (requests matching the CVE''s detection signatures) and the requests the interactive sensors answered that count as a probe for the CVE (the sensor''s rule for that CVE was the only one the request matched, on a path first contact''s exclusions accept, or the request or its session carried the exploit). A request that matched several CVE rules counts for none. UDP is left out on both sides.'
    CveInteraction:
      type:
      - object
      - 'null'
      description: 'What the interactive sensors recorded for this CVE: sessions in which a client went on to send the exploit after the sensor answered as the vulnerable service. null when there were none in the window. Hosts are defanged; render them as text, never as links.'
      properties:
        window_days:
          type: integer
        sessions:
          type: integer
        sources:
          type: integer
          description: Distinct source addresses behind the sessions.
        top_asns:
          type: array
          items:
            type: object
            properties:
              asn:
                type: integer
              org:
                type: string
              sessions:
                type: integer
        followed_by:
          type: object
          description: What the client did after sending the exploit.
          properties:
            downloads:
              type: integer
            commands:
              type: integer
            uploads:
              type: integer
              description: Sessions that handed the sensor a file other than the exploit's own body.
        download_hosts:
          type: array
          items:
            type: object
            properties:
              host:
                type: string
                description: Defanged, e.g. 203[.]0[.]113[.]9.
              sessions:
                type: integer
        recent:
          type: array
          items:
            type: object
            properties:
              ts:
                type: string
              country_code:
                type: string
              asn_org:
                type: string
              protocol:
                type: string
              dest_port:
                type: integer
              did:
                type: array
                items:
                  type: string
                description: 'What the session did in words: logged in, tried logins, ran commands, named a download, uploaded a file, sent an exploit. The sensor''s own labels are never published.'
    AsnReport:
      type: object
      properties:
        asn:
          type: integer
        org:
          type: string
        events:
          type: integer
        unique_ips:
          type: integer
        actors:
          type: array
          items:
            type: object
        ports:
          type: array
          items:
            type: object
        countries:
          type: array
          items:
            type: object
    IpReport:
      type: object
      properties:
        ip:
          type: string
        observed:
          type: boolean
          description: True when a first-packet event or an interactive TCP session reached a sensor.
        total_events:
          type: integer
          description: First-packet events only.
        verdict:
          $ref: '#/components/schemas/Verdict'
        first_seen:
          type:
          - string
          - 'null'
          description: Earliest of either source.
        last_seen:
          type:
          - string
          - 'null'
          description: Latest of either source.
        events_24h:
          type: integer
        events_7d:
          type: integer
        interactive_sessions:
          type: integer
          description: Interactive TCP sessions in the last 90 days. UDP sessions are left out of every overview field (a UDP source can be forged) and stay in interaction.
        interactive_sessions_24h:
          type: integer
        interactive_sessions_7d:
          type: integer
        interactive_protocols:
          type: array
          description: Protocols of those sessions, most used first.
          items:
            type: object
            properties:
              protocol:
                type: string
              sessions:
                type: integer
        distinct_ports_total:
          type: integer
          description: TCP ports across both sources, each port once.
        geo:
          type: object
          description: country_code, country_name, region, city, lat, lon, asn and org; they fall back to the interactive sessions' values where the first-packet data has none.
          properties:
            country_code:
              type: string
            country_name:
              type: string
            region:
              type: string
            city:
              type: string
            lat:
              type:
              - number
              - 'null'
            lon:
              type:
              - number
              - 'null'
            asn:
              type:
              - integer
              - 'null'
            org:
              type: string
        fingerprints:
          type: object
        recent_events:
          type: array
          items:
            type: object
        source_domain:
          type:
          - string
          - 'null'
          description: rDNS, falling back to the sessions' rDNS.
        top_ports:
          type: array
          description: At most 15, ranked by events and sessions together.
          items:
            type: object
            properties:
              port:
                type: integer
              proto:
                type: string
              label:
                type: string
              count:
                type: integer
                description: First-packet events.
              sessions:
                type: integer
                description: Interactive sessions on that port.
        timeline:
          type: array
          items:
            type: object
            properties:
              date:
                type: string
              count:
                type: integer
                description: First-packet events.
              sessions:
                type: integer
                description: Interactive sessions.
        cve_matches:
          type: array
          description: CVE signatures matched by this address's requests. A CVE whose payload an interactive session carried is a match with match_field "interactive_session" and confirmed_by "interactive_session". Each match carries actively_exploited (on the CISA KEV catalogue, or flagged by its signatures), kev_date_added (YYYY-MM-DD or null) and a title, taken the same way as on /api/cves.
          items:
            type: object
        interaction:
          type:
          - object
          - 'null'
          description: 'The Interaction group: sessions, logins, commands, downloads and files from the interactive sensors over 90 days. null when the address held no session.'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: Free key from https://honeylabs.net/dashboard
externalDocs:
  description: Docs with worked examples
  url: https://honeylabs.net/docs