apify/crawlee · error · TypeError

`Request` options must be an object, got the string '${optio

Error message

`Request` options must be an object, got the string '${options}'. Did you mean `new Request({ url })`?

What it means

The Request constructor expects a RequestOptions object. Passing a bare string (a common slip where developers assume new Request('https://...') works) throws a TypeError with a hint pointing at the object form new Request({ url }).

Source

Thrown at packages/core/src/request.ts:159

     *
     * All data stored in `userData` must be JSON-serializable.
     * Storing non-serializable values (e.g. functions, symbols) may result in unexpected results.
     */
    userData: UserData = {} as UserData;

    /**
     * ISO datetime string that indicates the time when the request has been processed.
     * Is `null` if the request has not been crawled yet.
     */
    handledAt?: string;

    /**
     * `Request` parameters including the URL, HTTP method and headers, and others.
     */
    constructor(options: RequestOptions<UserData>) {
        // A bare URL is a common slip — point at the object form instead of a generic type error.
        if (typeof options === 'string') {
            throw new TypeError(
                `\`Request\` options must be an object, got the string '${options}'. ` +
                    'Did you mean `new Request({ url })`?',
            );
        }

        parseArgument(options, schemas.anyObject, 'RequestOptions');
        parseArgument(options, requestUrlSchema, 'RequestOptions');
        // Full-shape validation is slow, because it checks all predicates
        // even if the validated object has only 1 property.
        // This custom validation loop iterates only over existing
        // properties and speeds up the validation cca 3-fold.
        keys(options).forEach((prop) => {
            // skip url, because it is validated above
            if (prop === 'url') {
                return;
            }

            const schema = requestOptionalSchemas[prop as string];

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Wrap the URL in an object: new Request({ url })
  2. If you have a Request-like value that may be a string, normalize it before construction
  3. Enable TypeScript checking so the RequestOptions type error surfaces at compile time

Example fix

// before
const request = new Request('https://example.com');
// after
const request = new Request({ url: 'https://example.com' });
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof options === 'string') throw new TypeError('Use new Request({ url })');

Type guard

function isRequestOptions(o: unknown): o is RequestOptions {
  return typeof o === 'object' && o !== null && 'url' in o;
}

Try / catch

try {
  return new Request(opts);
} catch (err) {
  if (err instanceof TypeError && err.message.includes('must be an object')) {
    return new Request({ url: String(opts) });
  }
  throw err;
}

Prevention

When it happens

Trigger: new Request('https://example.com') — passing a URL string directly instead of { url: 'https://example.com' }.

Common situations: Migrating from other HTTP libraries whose Request accepts a string; copy-pasted code from fetch-style APIs; TypeScript suppressed or JS code bypassing compile-time type errors.

Related errors


AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30). Data as JSON: /api/errors/d7550424d0d2f586. Report an issue: GitHub.