> ## Documentation Index
> Fetch the complete documentation index at: https://docs.graphy.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# URL

Fetch a remote file by URL and parse it into the [Data structure](/sdk/core/data-structure) expected by `@graphysdk/core`. The format is auto-detected from the URL path extension.

## fromURL

```typescript theme={null}
import { fromURL } from '@graphysdk/data-import-utils/url';

const data = await fromURL('https://example.com/sales.csv');
const data = await fromURL('https://example.com/report.xlsx', { sheet: 'Revenue' });
```

### Signature

```typescript theme={null}
function fromURL(
  url: string,
  options?: URLParseOptions
): Promise<Data>
```

## Options

<ParamField path="url" type="string" required>
  URL to fetch. The path extension determines the format, falling back to the
  response `Content-Type` header.
</ParamField>

<ParamField path="options.headers" type="Record<string, string>">
  Custom headers to include in the fetch request. Useful for authenticated
  endpoints (e.g. `{ Authorization: 'Bearer token' }`).
</ParamField>

<ParamField path="options.timeout" type="number" default="30000">
  Fetch timeout in milliseconds. The request is aborted if it takes longer.
</ParamField>

<ParamField path="options.signal" type="AbortSignal">
  Optional external abort signal for cancellation. Combined with the internal
  timeout signal via `AbortSignal.any`.
</ParamField>

<ParamField path="options.hasHeader" type="boolean" default="true">
  Whether the first row contains column headers (CSV/TSV only). When `false`,
  columns are auto-named `Column 1`, `Column 2`, etc.
</ParamField>

<ParamField path="options.sheet" type="string | number" default="0">
  Sheet to parse (spreadsheets only). Pass a sheet name or 0-based index.
</ParamField>

<ParamField path="options.locale" type="VizLocale" default="EN_US">
  Locale for number parsing. Determines thousand/decimal separator conventions.
</ParamField>

<ParamField path="options.maxFileSize" type="number" default="5">
  Maximum allowed input size in megabytes. The response body is streamed with a
  byte budget -- the download is aborted early if the limit is exceeded.
</ParamField>

<ParamField path="options.maxRows" type="number" default="100000">
  Maximum number of data rows to process (spreadsheets only).
</ParamField>

<ParamField path="options.maxCells" type="number" default="5000000">
  Maximum total cells to process (spreadsheets only).
</ParamField>

## Supported Extensions

| Extension      | Format |
| -------------- | ------ |
| `.csv`         | CSV    |
| `.tsv`, `.tab` | TSV    |
| `.xlsx`        | XLSX   |
| `.xls`         | XLS    |
| `.ods`         | ODS    |

Unsupported extensions throw an error listing the supported formats.

## Examples

### With the AI SDK

```typescript theme={null}
import { fromURL } from '@graphysdk/data-import-utils/url';
import { GraphyAiSdk } from '@graphysdk/agents-sdk';

const ai = new GraphyAiSdk({
  apiKey: process.env.GRAPHY_API_KEY,
  baseUrl: 'https://agents.graphy.dev',
});

const data = await fromURL('https://data.example.com/quarterly-sales.csv');

const result = await ai.generateGraph({
  config: { data },
  userPrompt: 'line chart showing quarterly trends',
});
```

### Error Handling

```typescript theme={null}
try {
  const data = await fromURL('https://example.com/data.pdf');
} catch (error) {
  // Error: Unsupported file extension ".pdf". Supported: .csv, .tsv, .tab, .xlsx, .xls, .ods
}
```

### With Custom Headers

```typescript theme={null}
const data = await fromURL('https://api.example.com/data.csv', {
  headers: { Authorization: 'Bearer my-token' },
});
```

### With Timeout and Cancellation

```typescript theme={null}
const controller = new AbortController();

const data = await fromURL('https://example.com/large-file.xlsx', {
  timeout: 10_000,
  signal: controller.signal,
});
```

<Warning>
  **SSRF Protection:** `fromURL` validates URLs before fetching. Private and
  reserved IP addresses (e.g. `127.0.0.1`, `10.x.x.x`, `192.168.x.x`,
  `169.254.x.x`, `localhost`, IPv6 loopback/link-local) are blocked, and only
  `http:` and `https:` schemes are allowed. This prevents server-side request
  forgery when URLs are provided by end users.
</Warning>

<Note>
  `fromURL` uses the global `fetch` API and works in Node.js 18+ and all modern
  browsers. For authenticated endpoints, you can either pass `headers` in the
  options or fetch the data yourself and use the format-specific parsers
  (`fromCSV`, `fromXLSX`, etc.) directly.
</Note>
