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
- Wrap the URL in an object: new Request({ url })
- If you have a Request-like value that may be a string, normalize it before construction
- 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
- Always construct with the object form new Request({ url })
- Let TypeScript check arguments instead of casting strings
- Wrap string-to-Request conversion in a helper that normalizes input
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
- Cannot activate BrowserController without an assigned browse
- BrowserController already has a browser instance assigned.
- Page with ID: ${id} already exists.
- Cannot extend LaunchContext with key: ${key}, because it's r
- The `body` property is not available - `skipNavigation` was
AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30).
Data as JSON: /api/errors/d7550424d0d2f586.
Report an issue: GitHub.