Delegated Stats¶
Delegated stats contain IP and ASN allocation records from the APNIC registry. These are the authoritative records of which IP blocks and AS numbers have been allocated to organizations in the APNIC region.
Overview¶
The delegated stats file follows the format defined by the five RIRs and contains records for IPv4 allocations, IPv6 allocations, and ASN assignments. Each record includes the registry, country code, resource type, starting address/count, date, and status.
flowchart TB
subgraph APNIC_FTP["APNIC FTP"]
Latest["delegated-apnic-latest"]
Archived["delegated-apnic-YYYYMMDD"]
ByYear["delegated-apnic-YYYY"]
end
FetchDelegatedEntries --> Latest
FetchDelegatedEntriesByDate --> Archived
FetchDelegatedByYear --> ByYear
subgraph Models["Result Models"]
Entry["DelegatedEntry<br/>registry|cc|type|start|value|date|status|opaque-id"]
Result["DelegatedResult<br/>Header + Summary + Entries"]
end
Latest --> Entry
Archived --> Result Methods¶
| Method | Description |
|---|---|
FetchDelegatedEntries(ctx) | Fetch latest standard delegated stats |
GetDelegatedEntries(ctx) | Cached standard delegated stats (30min TTL) |
FetchDelegatedEntriesByDate(ctx, date) | Fetch delegated stats by date (YYYYMMDD format) |
FetchDelegatedResult(ctx, date) | Full result with header/summary/entries |
FetchDelegatedByYear(ctx, year) | Fetch by year (last day of year) |
FetchDelegatedResultByYear(ctx, year) | Full result by year |
Method Signatures¶
// Fetch latest delegated stats, returns only entries
func (c *Client) FetchDelegatedEntries(ctx context.Context) ([]DelegatedEntry, error)
// Cached variant - fetches fresh data if cache expired
func (c *Client) GetDelegatedEntries(ctx context.Context) ([]DelegatedEntry, error)
// Fetch by specific date (YYYYMMDD format, e.g., "20240115")
func (c *Client) FetchDelegatedEntriesByDate(ctx context.Context, date string) ([]DelegatedEntry, error)
// Full result including header and summaries
func (c *Client) FetchDelegatedResult(ctx context.Context, date string) (*DelegatedResult, error)
// Fetch by year (returns data from December 31 of that year)
func (c *Client) FetchDelegatedByYear(ctx context.Context, year int) ([]DelegatedEntry, error)
func (c *Client) FetchDelegatedResultByYear(ctx context.Context, year int) (*DelegatedResult, error)
Data Structures¶
DelegatedEntry¶
type DelegatedEntry struct {
Registry string // "apnic"
Country string // ISO 3166-1 alpha-2 country code (e.g., "JP", "CN", "AU")
Type string // "ipv4", "ipv6", or "asn"
Start string // Starting address or AS number
Value int64 // Count (IPv4: number of IPs, IPv6: prefix length, ASN: count)
Date time.Time // Allocation/assignment date
Status string // "allocated", "assigned", "available", "reserved"
Extensions []string // Additional fields (opaque-id in extended format)
}
DelegatedResult¶
type DelegatedResult struct {
Header StatsFileHeader // File metadata
Summaries []StatsSummary // Per-type summaries
Entries []DelegatedEntry // Data records
}
type StatsFileHeader struct {
Version string // File format version
Registry string // "apnic"
Serial int64 // Serial number
Records int64 // Total record count
StartDate time.Time // Data start date
EndDate time.Time // Data end date
UTCOffset int // UTC offset in seconds
}
type StatsSummary struct {
Registry string // "apnic"
Type string // "asn", "ipv4", or "ipv6"
Count int64 // Number of records
}
Data Flow¶
flowchart LR
subgraph Request["Request"]
Call["FetchDelegatedEntries(ctx)"]
DateOpt["date parameter<br/>(optional)"]
end
subgraph URL["URL Construction"]
LatestURL["ftp.apnic.net/pub/stats/apnic/delegated-apnic-latest"]
DateURL["ftp.apnic.net/pub/stats/apnic/delegated-apnic-YYYYMMDD"]
YearURL["ftp.apnic.net/pub/stats/apnic/YYYY/delegated-apnic-YYYY1231.gz"]
end
subgraph Processing["Processing"]
Download["Chunked Download<br/>(4 concurrent × 2MiB)"]
Parse["Line-by-line Parse"]
Validate["Type-specific Validation"]
end
subgraph Output["Output"]
Entries["[]DelegatedEntry"]
Result["DelegatedResult"]
end
Call --> DateOpt
DateOpt -->|empty| LatestURL
DateOpt -->|YYYYMMDD| DateURL
DateOpt -->|year| YearURL
LatestURL --> Download --> Parse --> Validate --> Entries
DateURL --> Download --> Parse --> Validate --> Result Examples¶
Basic Usage¶
package main
import (
"context"
"fmt"
"log"
apnic "github.com/cyberspacesec/apnic-skills"
)
func main() {
client := apnic.NewClient()
ctx := context.Background()
// Fetch latest delegated stats
entries, err := client.FetchDelegatedEntries(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total entries: %d\n", len(entries))
// Print first 5 IPv4 entries
count := 0
for _, entry := range entries {
if entry.Type == "ipv4" && count < 5 {
fmt.Printf("%s: %s/%d (%s) - %s\n",
entry.Country, entry.Start, entry.Value, entry.Status, entry.Date.Format("2006-01-02"))
count++
}
}
}
Fetching by Date¶
// Fetch delegated stats for a specific date
result, err := client.FetchDelegatedResult(ctx, "20240115")
if err != nil {
log.Fatal(err)
}
fmt.Printf("File version: %s\n", result.Header.Version)
fmt.Printf("Records: %d\n", result.Header.Records)
fmt.Printf("Date range: %s to %s\n",
result.Header.StartDate.Format("2006-01-02"),
result.Header.EndDate.Format("2006-01-02"))
// Print summaries
for _, summary := range result.Summaries {
fmt.Printf("%s: %d records\n", summary.Type, summary.Count)
}
Fetching by Year¶
// Fetch delegated stats from December 31, 2023
entries, err := client.FetchDelegatedByYear(ctx, 2023)
if err != nil {
log.Fatal(err)
}
fmt.Printf("2023 year-end entries: %d\n", len(entries))
Using Cached Data¶
// First call fetches from network
entries1, err := client.GetDelegatedEntries(ctx)
if err != nil {
log.Fatal(err)
}
// Second call returns cached data (within TTL)
entries2, err := client.GetDelegatedEntries(ctx)
if err != nil {
log.Fatal(err)
}
// Both return the same data
fmt.Printf("Same data: %v\n", len(entries1) == len(entries2))
Filtering Entries¶
// Filter by country and type
entries, err := client.GetDelegatedEntries(ctx)
if err != nil {
log.Fatal(err)
}
// Use chain filtering
cnIPv4 := apnic.NewFilter(entries).
ByCountry("CN").
ByType("ipv4").
ByStatus("allocated").
Result()
fmt.Printf("China allocated IPv4 entries: %d\n", len(cnIPv4))
// Filter by date range
start, _ := time.Parse("2006-01-02", "2023-01-01")
end, _ := time.Parse("2006-01-02", "2023-12-31")
recentAllocs := apnic.NewFilter(entries).
ByType("ipv4").
ByDateRange(start, end).
Result()
CIDR Calculation¶
// Convert entry to CIDR notation
entries, _ := client.GetDelegatedEntries(ctx)
for _, entry := range entries {
if entry.Type == "ipv4" {
cidr, err := entry.CIDR()
if err != nil {
continue
}
fmt.Printf("%s -> %s (size: %d IPs)\n",
entry.Start, cidr.String(), entry.Value)
break // Just show first
}
}
File Format¶
The delegated stats file uses pipe-delimited format:
# Version, Registry, Serial, Records, Start-Date, End-Date, UTC-Offset
2|apnic|1737030783|45837|20240101|20240116|0
# Summary lines (registry|*|type|count)
apnic|*|ipv4|12345
apnic|*|ipv6|2345
apnic|*|asn|567
# Data lines (registry|cc|type|start|value|date|status[|extensions])
apnic|AU|ipv4|1.0.0.0|256|20110811|allocated
apnic|CN|ipv6|2001:200::|32|19990714|allocated
apnic|JP|asn|173|1|19930101|allocated
Status Values¶
| Status | Description |
|---|---|
allocated | Allocated to an LIR (Local Internet Registry) |
assigned | Assigned to an end user or ISP |
available | Not yet allocated (available pool) |
reserved | Reserved for special purposes |
Resource Types¶
| Type | Value Meaning |
|---|---|
ipv4 | Number of IP addresses in the block |
ipv6 | Prefix length (e.g., 32 means /32) |
asn | Number of consecutive AS numbers |
Data Sources¶
The data is sourced from APNIC's FTP server:
- Latest:
ftp://ftp.apnic.net/pub/stats/apnic/delegated-apnic-latest - Archived:
ftp://ftp.apnic.net/pub/stats/apnic/delegated-apnic-YYYYMMDD - By Year:
ftp://ftp.apnic.net/pub/stats/apnic/YYYY/delegated-apnic-YYYY1231.gz
See Also¶
- Extended Stats - Delegated stats with organization opaque-IDs
- Assigned Stats - Aggregated assignment counts by prefix size
- Legacy Stats - Historical pre-APNIC resource records