Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 63 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Based on:
- [`bulk-ip-geo` Usage](#bulk-ip-geo-usage)
- [Flags for `bulk-ip-geo`](#flags-for-bulk-ip-geo)
- [Output Formats](#output-formats)
- [CSV Output](#csv-output)
- [`ip-security` Command](#ip-security-command)
- [`ip-security` Usage](#ip-security-usage)
- [Flags for `ip-security`](#flags-for-ip-security)
Expand Down Expand Up @@ -332,7 +333,7 @@ ipgeolocation my-ip [flags]

| Flag | Type | Default | Description |
|------------|--------|----------|----------------------------------------------------------|
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `text`. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`, `text`. |

> [!NOTE]
> - The `my-ip` command does not require an API key.
Expand Down Expand Up @@ -382,7 +383,7 @@ ipgeolocation ipgeo [flags]
| `--fields` | string[] | `[]` | Return only specific fields (e.g. `location,asn.organization`). |
| `--exclude` | string[] | `[]` | Exclude fields from output. `--excludes` is also accepted. |
| `--lang` | string | `""` | Response language. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`. |

> [!NOTE]
> Available language options are listed in [Response in multiple languages](https://ipgeolocation.io/documentation/ip-location-api.html#response-in-multiple-languages)
Expand Down Expand Up @@ -979,8 +980,8 @@ ipgeolocation bulk-ip-geo [flags]
| `--exclude` | string[] | `[]` | Exclude fields (e.g. `currency`). |
| `--fields` | string[] | `[]` | Return only specific fields (e.g. `location,time_zone`). |
| `--lang` | string | `""` | Response language (if supported). |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`. |
| `--output-file` | string | `""` | Save output to JSON file. Example: `--output-file results` |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`. |
| `--output-file` | string | `""` | Save output to a file. Writes `.csv` with `--output csv`, otherwise `.json`; the extension is added only if the name lacks it. Example: `--output-file results` or `--output-file results.csv` |


For further information, please visit [IP Geolocation API Documentation](https://ipgeolocation.io/documentation/ip-location-api.html).
Expand Down Expand Up @@ -1010,12 +1011,56 @@ Save results to JSON file:
ipgeolocation bulk-ip-geo --ips=8.8.8.8,1.1.1.1 --output-file=output.json
```

Results will be written to the `output.json` file. The `.json` is not added twice, because the name already ends in it.

#### Output Formats
- **pretty** (default): Human-readable formatted JSON.
- **raw**: Raw API response.
- **table**: Tabular display of common fields.
- **yaml**: YAML-formatted output.
- **json file**: If `--output-file` is provided, results are saved to a `.json` file.
- **csv**: Spreadsheet-friendly CSV. See [CSV Output](#csv-output).
- **file**: If `--output-file` is provided, results are saved to a file. With `--output csv` the file is `.csv`; otherwise it is `.json`. The extension is appended only when the name does not already end in it, so `results` and `results.csv` both save to `results.csv`.

### CSV Output
Every command accepts `--output csv`, which renders the response as CSV for spreadsheets, `awk`, `cut`, or a database import.

```bash
ipgeolocation ipgeo --ip 8.8.8.8 --output csv
```
Sample output:
```csv
asn.as_number,asn.country,asn.organization,country_metadata.calling_code,country_metadata.languages,currency.code,ip,location.city,location.is_eu,location.latitude,time_zone.name,time_zone.offset
AS15169,US,Google LLC,+1,en-US|es-US|haw|fr,USD,8.8.8.8,Mountain View,false,37.42240,America/Los_Angeles,-8
```

How a response becomes CSV:

| Response shape | CSV result |
|---|---|
| A top-level array, as the bulk commands return | One row per record |
| Anything else | A single row |
| A nested object | Dotted column names, e.g. `location.city` |
| An array of scalars | Joined into one cell with `\|`, e.g. `en-US\|es-US\|haw` |
| An array of objects | A column per element, e.g. `routes.0.prefix` |
| `null`, `[]` or `{}` | An empty cell |

Notes:
- Columns are the union of the fields of every row, sorted by name, so the same response always produces the same file. Where one record lacks a field another has, its cell is empty.
- Numbers are written exactly as the API returned them, so Unix timestamps and long identifiers keep every digit.
- Values containing a comma, quote, or newline are quoted per RFC 4180. A value that itself contains `|` is indistinguishable from the array separator.
- A value beginning with `=`, `@`, a tab, or a carriage return is prefixed with `'` so a spreadsheet does not run it as a formula, as is a `+` or `-` followed by a non-digit, such as `+SUM(A1)`. A sign followed by a digit, and a sign on its own, are data and are left alone, so a `-122.08421` coordinate, a `-8` offset, a `+1` calling code, the `+1.00H` and `-1.00H` DST durations, and the lone `-` the astronomy endpoint reports for an absent `sun_status` or `moon_status` all stay exactly as the API sent them.

Save CSV straight to a file with `--output-file` on the bulk commands:
```bash
ipgeolocation bulk-ip-geo --file=ips.txt --output csv --output-file results
```
This writes `results.csv`. Passing `--output-file results.csv` writes the same file — the extension is added only when it is missing. Without `--output csv` the same flag writes `results.json`.

For the other commands, redirect the output:
```bash
ipgeolocation ipgeo --ip 8.8.8.8 --output csv > ipgeo.csv
```


### `ip-security` Command
Look up IP security information using the `ipgeolocation.io` API.
Expand All @@ -1031,7 +1076,7 @@ ipgeolocation ip-security [flags]
| `--ip` | string | `""` | IPv4 or IPv6 address. |
| `--exclude` | string[] | `[]` | Exclude fields from output. |
| `--fields` | string[] | `[]` | Return only specific fields (e.g. `security.threat_score`). |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`. |

> [!NOTE]
> IP Security API is only available in the Paid Plan
Expand Down Expand Up @@ -1121,8 +1166,8 @@ ipgeolocation bulk-ip-security [flags]
| `--file` | string | `""` | Path to a text file containing IPs (one per line). |
| `--exclude` | string[] | `[]` | Exclude fields (e.g. `security.is_tor`). |
| `--fields` | string[] | `[]` | Return only specific fields (e.g. `security.threat_score`). |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`. |
| `--output-file` | string | `""` | Save output to JSON file. Example: `--output-file results` |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`. |
| `--output-file` | string | `""` | Save output to a file. Writes `.csv` with `--output csv`, otherwise `.json`; the extension is added only if the name lacks it. Example: `--output-file results` or `--output-file results.csv` |

#### `bulk-ip-security` Examples
Look up 3 IP addresses:
Expand All @@ -1135,6 +1180,8 @@ Look up from a file:
ipgeolocation bulk-ip-security --file=ips.txt --output-file=output
```

Results will be written to the `output.json` file.

Output as YAML:
```bash
ipgeolocation bulk-ip-security --ips=8.8.8.8 --output=yaml
Expand Down Expand Up @@ -1162,7 +1209,7 @@ ipgeolocation asn [flags]
| `--include` | string[] | `[]` | Include extra fields in output.(e.g., `peers,downstreams,upstreams,routes,whois_response`) |
| `--exclude` | string[] | `[]` | Exclude fields from output. |
| `--fields` | string[] | `[]` | Return only specific fields (e.g. `ip,organization`). |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`. |

> [!NOTE]
> ASN API is only available in the Paid Plan
Expand Down Expand Up @@ -1313,7 +1360,7 @@ ipgeolocation abuse [flags]
| `--ip` | string | `""` | IPv4 or IPv6 address. |
| `--exclude` | string[] | `[]` | Exclude fields from output. |
| `--fields` | string[] | `[]` | Return only specific fields (e.g. `ip,organization`). |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`. |

> [!NOTE]
> Abuse Contact API is only available in the Paid Plan
Expand Down Expand Up @@ -1395,7 +1442,7 @@ ipgeolocation timezone [flags]
| `--iata` | string | `""` | IATA code (e.g. DXB). |
| `--icao` | string | `""` | ICAO code (e.g. KATL). |
| `--lo` | string | `""` | LO code (e.g. DEBER). |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`. |

#### Get time zone info about your current IP
```bash
Expand Down Expand Up @@ -1792,7 +1839,7 @@ ipgeolocation time-conversion [flags]
| `--lo_from` | string | `""` | LO code to convert from. |
| `--lo_to` | string | `""` | LO code to convert to. |
| `--time` | string | `""` | Time to convert. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`. |

#### Convert Current Time from One Timezone to Another
```bash
Expand Down Expand Up @@ -1868,7 +1915,7 @@ ipgeolocation astronomy [flags]
| `--lang` | string | `""` | Response language (if supported). |
| `--tz` | string | `""` | IANA time zone for output timestamps. |
| `--elevation` | float64 | `0` | Elevation. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`. |

#### Lookup Astronomy API by Coordinates
Get astronomy info about a specific latitude and longitude:
Expand Down Expand Up @@ -2119,7 +2166,7 @@ ipgeolocation astronomy-timeseries [flags]
| `--lang` | string | `""` | Response language (if supported). |
| `--start-date` | string | `""` | Start date (e.g. 2023-01-01) Only YYYY-MM-DD. |
| `--end-date` | string | `""` | End date (e.g. 2023-12-31) Only YYYY-MM-DD |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`. |

> [!NOTE]
> - The `start-date` and `end-date` flags are required.
Expand Down Expand Up @@ -2256,7 +2303,7 @@ ipgeolocation parse-user-agent [flags]
| Flag | Type | Default | Description |
|----------------|--------|----------|--------------------------------------------------|
| `--user-agent` | string | `""` | User agent string. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`. |

For further information, please visit [User Agent API Documentation](https://ipgeolocation.io/documentation/user-agent-api.html).

Expand Down Expand Up @@ -2313,7 +2360,7 @@ ipgeolocation parse-bulk-user-agents [flags]
| Flag | Type | Default | Description |
|-----------------|----------|----------|--------------------------------------------------|
| `--user-agents` | string[] | `[]` | User agent strings. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`. |
| `--output` | string | `pretty` | Output format: `pretty`, `raw`, `table`, `yaml`, `csv`. |

For further information, please visit [User Agent API bulk parsing documentation](https://ipgeolocation.io/documentation/user-agent-api.html#parse-bulk-user-agent-strings).

Expand Down
9 changes: 8 additions & 1 deletion cmd/abuse.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ Example:
fmt.Println(string(body))
case "table":
utils.PrintAsTable(result, 0)
case "csv":
csvData, err := utils.ConvertToCSV(body)
if err != nil {
fmt.Println("Error converting to CSV:", err)
return
}
fmt.Print(csvData)
case "yaml":
yamlData, err := yaml.Marshal(result)
if err != nil {
Expand All @@ -84,7 +91,7 @@ func init() {
abuseCmd.Flags().StringVar(&abuseFlags.IP, "ip", "", "IPv4 or IPv6 address (e.g. 8.8.8.8)")
abuseCmd.Flags().StringSliceVar(&abuseFlags.Excludes, "exclude", []string{}, "Fields to exclude from the output")
abuseCmd.Flags().StringSliceVar(&abuseFlags.Fields, "fields", []string{}, "Get Specific Fields to include in the output")
abuseCmd.Flags().StringVar(&abuseFlags.Output, "output", "", "Output format: yaml, raw, table, yaml")
abuseCmd.Flags().StringVar(&abuseFlags.Output, "output", "", "Output format: pretty, raw, table, yaml, csv")

rootCmd.AddCommand(abuseCmd)
}
9 changes: 8 additions & 1 deletion cmd/asn.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ Getting peering relationships for an ASN number: ipgeolocation asn --asn 12345 -
fmt.Println(string(body))
case "table":
utils.PrintAsTable(result, 0)
case "csv":
csvData, err := utils.ConvertToCSV(body)
if err != nil {
fmt.Println("Error converting to CSV:", err)
return
}
fmt.Print(csvData)
case "yaml":
yamlData, err := yaml.Marshal(result)
if err != nil {
Expand All @@ -96,7 +103,7 @@ func init() {
asnCmd.Flags().StringSliceVar(&asnFlags.Include, "include", []string{}, "To include additional values in the output")
asnCmd.Flags().StringSliceVar(&asnFlags.Excludes, "exclude", []string{}, "Fields to exclude from the output")
asnCmd.Flags().StringSliceVar(&asnFlags.Fields, "fields", []string{}, "Get Specific Fields to include in the output")
asnCmd.Flags().StringVar(&asnFlags.Output, "output", "pretty", "Output format: pretty, raw, table")
asnCmd.Flags().StringVar(&asnFlags.Output, "output", "pretty", "Output format: pretty, raw, table, yaml, csv")

rootCmd.AddCommand(asnCmd)
}
9 changes: 8 additions & 1 deletion cmd/astronomy.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ API Reference: https://ipgeolocation.io/astronomy-api.html
fmt.Println(string(body))
case "table":
utils.PrintAsTable(result, 0)
case "csv":
csvData, err := utils.ConvertToCSV(body)
if err != nil {
fmt.Println("Error converting to CSV:", err)
return
}
fmt.Print(csvData)
case "yaml":
yamlData, err := yaml.Marshal(result)
if err != nil {
Expand All @@ -122,7 +129,7 @@ func init() {
astronomyCmd.Flags().Float64Var(&astronomyFlags.Longitude, "longitude", 0, "Longitude (e.g. -122.4194)")
astronomyCmd.Flags().StringVar(&astronomyFlags.Language, "lang", "", "Language code (e.g. en)")
astronomyCmd.Flags().Float64Var(&astronomyFlags.Elevation, "elevation", 0, "Elevation (e.g. 1000)")
astronomyCmd.Flags().StringVar(&astronomyFlags.Output, "output", "pretty", "Output format: pretty, raw, table")
astronomyCmd.Flags().StringVar(&astronomyFlags.Output, "output", "pretty", "Output format: pretty, raw, table, yaml, csv")

rootCmd.AddCommand(astronomyCmd)
}
9 changes: 8 additions & 1 deletion cmd/astronomyTimeseries.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ Examples:
fmt.Println(string(body))
case "table":
utils.PrintAsTable(result, 0)
case "csv":
csvData, err := utils.ConvertToCSV(body)
if err != nil {
fmt.Println("Error converting to CSV:", err)
return
}
fmt.Print(csvData)
case "yaml":
yamlData, err := yaml.Marshal(result)
if err != nil {
Expand All @@ -117,7 +124,7 @@ func init() {
astronomyTimeseriesCmd.Flags().Float64Var(&astronomyTimeseriesFlags.Latitude, "latitude", 0, "Latitude (e.g. 37.7749)")
astronomyTimeseriesCmd.Flags().Float64Var(&astronomyTimeseriesFlags.Longitude, "longitude", 0, "Longitude (e.g. -122.4194)")
astronomyTimeseriesCmd.Flags().StringVar(&astronomyTimeseriesFlags.Language, "lang", "", "Language code (e.g. en)")
astronomyTimeseriesCmd.Flags().StringVar(&astronomyTimeseriesFlags.Output, "output", "pretty", "Output format: pretty, raw, table, yaml")
astronomyTimeseriesCmd.Flags().StringVar(&astronomyTimeseriesFlags.Output, "output", "pretty", "Output format: pretty, raw, table, yaml, csv")

rootCmd.AddCommand(astronomyTimeseriesCmd)
}
34 changes: 27 additions & 7 deletions cmd/bulkIpSecurity.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ Retrieving security information for IP addresses from a file: ipgeolocation bulk
fmt.Println(string(body))
case "table":
utils.PrintAsTable(result, 0)
case "csv":
csvData, err := utils.ConvertToCSV(body)
if err != nil {
fmt.Println("Error converting to CSV:", err)
return
}
fmt.Print(csvData)
case "yaml":
yamlData, err := yaml.Marshal(result)
if err != nil {
Expand All @@ -108,13 +115,26 @@ Retrieving security information for IP addresses from a file: ipgeolocation bulk
fmt.Println(string(pretty))
}
if bulkSecurityFlags.OutputFile != "" {
pretty, _ := json.MarshalIndent(result, "", " ")
err := os.WriteFile(bulkSecurityFlags.OutputFile+".json", pretty, 0644)
if err != nil {
fmt.Println("Error writing JSON to file:", err)
// The saved file matches --output, so --output csv saves .csv and
// every other format keeps saving the .json it always has. The
// extension is only appended when the given name lacks it.
extension := ".json"
data, _ := json.MarshalIndent(result, "", " ")
if bulkSecurityFlags.Output == "csv" {
csvData, err := utils.ConvertToCSV(body)
if err != nil {
fmt.Println("Error converting to CSV:", err)
return
}
extension = ".csv"
data = []byte(csvData)
}
path := utils.OutputFilePath(bulkSecurityFlags.OutputFile, extension)
if err := os.WriteFile(path, data, 0644); err != nil {
fmt.Println("Error writing output to file:", err)
return
}
fmt.Println("Output saved to file:", bulkSecurityFlags.OutputFile+".json")
fmt.Println("Output saved to file:", path)
}
},
}
Expand All @@ -123,9 +143,9 @@ func init() {
bulkIpSecurityCmd.Flags().StringSliceVar(&bulkSecurityFlags.IPs, "ips", []string{}, "IPs")
bulkIpSecurityCmd.Flags().StringSliceVar(&bulkSecurityFlags.Excludes, "exclude", []string{}, "Fields to exclude from the output")
bulkIpSecurityCmd.Flags().StringSliceVar(&bulkSecurityFlags.Fields, "fields", []string{}, "Get Specific Fields to include in the output")
bulkIpSecurityCmd.Flags().StringVar(&bulkSecurityFlags.Output, "output", "pretty", "Output format: pretty, raw, table")
bulkIpSecurityCmd.Flags().StringVar(&bulkSecurityFlags.Output, "output", "pretty", "Output format: pretty, raw, table, yaml, csv")
bulkIpSecurityCmd.Flags().StringVar(&bulkSecurityFlags.File, "file", "", "Path to a text file containing IPs (one per line)")
bulkIpSecurityCmd.Flags().StringVar(&bulkSecurityFlags.OutputFile, "output-file", "", "Save output to a file (JSON only)")
bulkIpSecurityCmd.Flags().StringVar(&bulkSecurityFlags.OutputFile, "output-file", "", "Save output to a file; the .csv or .json extension is added only if missing")

rootCmd.AddCommand(bulkIpSecurityCmd)
}
Loading