sindresorhus/got · error · TypeError

Missing `url` property

Error message

Missing `url` property

What it means

Thrown at source/core/index.ts:393 during Request construction. After Options merges the input, got expects a resolvable URL — either from the first argument, from `url`, or composed from `prefixUrl` plus a relative path. If `options.url` is still falsy AND `prefixUrl` is the empty string (the default), there is no base to derive a URL from, so got throws a TypeError. The check is a hard precondition for any HTTP request: without a URL there is nothing to connect to.

Source

Thrown at source/core/index.ts:393

					}

					this.options.setPipedHeader(normalizedHeader, value);
				}
			}
		});

		this.on('newListener', event => {
			if (event === 'retry' && this.listenerCount('retry') > 0) {
				throw new Error('A retry listener has been attached already.');
			}
		});

		try {
			this.options = new Options(url, options, defaults);

			if (!this.options.url) {
				if (this.options.prefixUrl === '') {
					throw new TypeError('Missing `url` property');
				}

				this.options.url = '';
			}

			this.requestUrl = this.options.url as URL;

			// Publish request creation event
			publishRequestCreate({
				requestId: this._requestId,
				url: getSanitizedUrl(this.options),
				method: this.options.method,
			});
		} catch (error: unknown) {
			const {options} = error as OptionsError;
			if (options) {
				this.options = options;
			}

View on GitHub (pinned to e3924aa1e5)

Solutions

  1. Pass a non-empty URL string or URL object as the first argument: `got('https://example.com')`.
  2. Or set `prefixUrl` on the instance (`got.extend({ prefixUrl: 'https://example.com' })`) so relative paths in calls resolve to a full URL.
  3. If the URL comes from configuration, validate it is a non-empty string before invoking got.

Example fix

// before
await got({ method: 'GET', headers: { accept: 'application/json' } });

// after
await got('https://api.example.com/resource', {
  method: 'GET',
  headers: { accept: 'application/json' }
});

// or via extend
const api = got.extend({ prefixUrl: 'https://api.example.com' });
await api('resource', { searchParams: { id: 1 } });
Defensive patterns

Strategy: validation

Validate before calling

function assertUrlProvided(url, options) {
  const hasUrlArg = typeof url === 'string' && url.length > 0 || url instanceof URL;
  const hasOptionsUrl = options && typeof options.url === 'string' && options.url.length > 0;
  const hasPrefixUrl = options && typeof options.prefixUrl === 'string' && options.prefixUrl.length > 0;
  if (!hasUrlArg && !hasOptionsUrl && !hasPrefixUrl) {
    throw new TypeError('got requires a url argument or a prefixUrl; received neither');
  }
}

// before each call:
assertUrlProvided(url, options);
await got(url, options);

Type guard

function isNonEmptyUrl(v: unknown): v is string | URL {
  if (v instanceof URL) return v.href.length > 0;
  return typeof v === 'string' && v.trim().length > 0;
}

Try / catch

try {
  await got(url, options);
} catch (error) {
  if (error instanceof TypeError && /Missing `url` property/.test(error.message)) {
    throw new Error('Configuration error: no URL provided to got. Set prefixUrl or pass a URL.', { cause: error });
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling `got()` or `got('')` with no URL and no prefixUrl; calling `got({ method: 'GET' })` with only options but no url; calling a got instance created with `got.extend({ method: 'POST' })` and then invoking it without a URL argument.

Common situations: Forgetting the URL argument when refactoring a call to pass only an options object; building a got instance with extend() but putting the URL inside extend() (it doesn't accept url there); env-driven code where the URL comes from a config variable that is unexpectedly undefined.

Related errors


AI-assisted analysis of sindresorhus/got@e3924aa1e5 (2026-08-03). Data as JSON: /data/errors/26abb873088bb748.json. Report an issue: GitHub.