qURL Proxy is a non-caching, Node.js HTTP proxy that supports batch requests and is driven by URL query. Headers, methods, bodies, and status codes can be overridden, and headers can also be deleted using wildcards. Responses can be transformed through custom JavaScript logic, which can chain requests and merge responses. It also supports retries with exponential backoff, timeouts, throttling and optional limits on request batching and recursion. By default it strips sensitive request headers and bypasses CORS response restrictions, useful for debugging and development. Notes · Examples
- Public instance - clone
- Local instance -
npm start - CLI instance (no client) -
npx -y qurl-proxy
import {createProxy} from 'qurl-proxy'
const proxy = createProxy(config)
const response = await proxy(request)key- API secret, if requiredurl- resource URL,httpassumed, required, repeatable (max.16), first response used, other statuses in comma-separatedX-Proxy-Responsesfastest- return first available response and its index inX-Proxy-Responses, abort othersheaders- JSON or JSONCrush object of request headers to overwrite (Hostis determined dynamically)delheaders- JSON or JSONCrush array of names of request headers to delete (Connectionis deleted along with headers listed in it,*is a wildcard), in addition to:resheaders- JSON or JSONCrush object of response headers to overwrite (Access-Control-Allow-OriginandAccess-Control-Expose-Headersare set automatically), in addition to:{ "Access-Control-Allow-Headers": "*", "Access-Control-Allow-Credentials": "true", "Cross-Origin-Resource-Policy": "cross-origin", "Timing-Allow-Origin": "*" }delresheaders- JSON or JSONCrush array of names of response headers to delete (Connectionis deleted along with headers listed in it,*is a wildcard), in addition to:[ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers#hop-by-hop_headers "Connection", "Keep-Alive", "Proxy-Authenticate", "Trailer", "Transfer-Encoding", "Upgrade", ]
renresheaders- rename response headers toX-Original-*before changesskipdefaults- do not apply default header changes, except response safety behavior and setting responseX-Proxy-Recursion(max.16)method- request method overridebody- request body textresbody- response transformation:null- remove response bodyatob- decode body from Base64btoa- encode body to Base64javascript:…- custom handler, returns body, response or request
status- response status code to overwriteretry- retries after first requestretryin- milliseconds between retries, supports exponential backoff:
min(in * factorattempt, limit)retryfactor- backoff multiplier per retry (default is1, industry standard is2)retrylimit- backoff maximum millisecondstimeout- milliseconds to abort request after (default is300000)ttfb- milliseconds to first response bytethrottle- bidirectional bandwidth limit in kbit/sthrottleup- upload bandwidth limit in kbit/s
// https://github.com/nodejs/undici/issues/2514
if (headers.get('Content-Encoding')) {
headers.delete('Content-Encoding')
headers.delete('Content-Length')
}
// recompress
const contentEncoding = resolveAcceptHeader(headers.get('Accept-Encoding')) || 'gzip'
if (contentEncoding !== 'identity') {
headers.set('Content-Encoding', contentEncoding)
headers.delete('Content-Length')
headers.set('Transfer-Encoding', 'chunked')
}
// resbody param
if (['null', 'atob', 'btoa'].includes(params.get('resbody')?.toLowerCase()))
headers.delete('Content-Length')After running resbody custom handler
if (!result instanceof Request && !result instanceof Response && result !== undefined)
headers.delete('Content-Length')declare function custom(
// request with parameters applied
req: RequestView,
// first or fastest response with parameters applied
res: ResponseView,
// other responses, null if error
responses: Array<ResponseView | null>
): CustomResult
interface ReqResView {
url: string
headers: Record<string, string>
// body:
body: ReadableStream | null
bytes: Uint8Array
text: string
json: any
}
interface RequestView extends ReqResView {
method: string
}
interface ResponseView extends ReqResView {
cookies: string[]
ok: boolean
redirected: boolean
status: number
statusText: string
}
type CustomResult =
| Request // replace original request and refetch response
| Response // replace original response
| undefined // return original response
| ReadableStream | Uint8Array // replace response body with value
| unknown // replace response body with coerced value?.toString()
| null // remove response body- Keep entire URL under deployment platform limit, 14 KB for Vercel
- Escape complex parameters (
url,body,resbody=javascript:…) resbodycustom handlers support most of ES2025, crypto object and following Web APIs:
Licensed under the Apache License, Version 2.0. See: