diff --git a/api/v2/1.yml b/api/v2/1.yml new file mode 100644 index 0000000..eeab9c2 --- /dev/null +++ b/api/v2/1.yml @@ -0,0 +1,73 @@ +openapi: 3.0.2 +info: + title: Content API + version: 2.0.0 +servers: + - url: https://production-sfo.browserless.io +paths: + /content: + post: + summary: Fetches the page's content + parameters: + - name: token + in: query + required: true + schema: + type: string + description: API token + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + url: + type: string + description: The URL to navigate to + gotoOptions: + type: object + description: Modifies the default navigation behavior for the requested URL. + bestAttempt: + type: boolean + description: Causes Browserless to continue when async events fail or timeout. + rejectResourceTypes: + type: array + items: + type: string + description: A list of resource types to block + rejectRequestPattern: + type: array + items: + type: string + description: A list of regex patterns to block certain requests + waitForEvent: + type: object + description: Waits for an event to happen on the page before continuing + waitForFunction: + type: object + description: Waits for the provided function to return before continuing + waitForSelector: + type: object + description: Wait for a selector to appear in the page + waitForTimeout: + type: integer + description: Maximum number of milliseconds to wait + examples: + example1: + summary: Basic Request + value: + url: "https://example.com/" + example2: + summary: Request with Navigation Options + value: + url: "https://example.com/" + gotoOptions: { "waitUntil": "networkidle2" } + responses: + '200': + description: Success + content: + text/html: + schema: + type: string + description: The site's HTML after it has been rendered and evaluated inside the browser. diff --git a/api/v2/10.yml b/api/v2/10.yml new file mode 100644 index 0000000..0bd6dde --- /dev/null +++ b/api/v2/10.yml @@ -0,0 +1,90 @@ +openapi: 3.0.0 +info: + title: Browserless.io API + version: v2 +servers: + - url: https://production-sfo.browserless.io/ + - url: https://production-lon.browserless.io/ +paths: + /config: + get: + summary: Get your worker's configuration + operationId: getWorkerConfig + parameters: + - name: token + in: query + required: true + schema: + type: string + example: MY_API_TOKEN + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + allowCORS: + type: boolean + allowFileProtocol: + type: boolean + allowGetCalls: + type: boolean + concurrent: + type: integer + data: + type: string + debug: + type: string + errorAlertURL: + type: string + healthFailureURL: + type: string + host: + type: string + maxCPU: + type: integer + maxMemory: + type: integer + metricsJSONPath: + type: string + port: + type: integer + queued: + type: integer + queuedAlertURL: + type: string + rejectAlertURL: + type: string + retries: + type: integer + timeout: + type: integer + timeoutAlertURL: + type: string + token: + type: string + example: + allowCORS: true + allowFileProtocol: false + allowGetCalls: false + concurrent: 10 + data: "/tmp/browserless-data-dirs" + debug: "browserless*,-**:verbose" + errorAlertURL: null + healthFailureURL: null + host: "localhost" + maxCPU: 99 + maxMemory: 99 + metricsJSONPath: "/tmp/browserless-metrics.json" + port: 3001 + queued: 10 + queuedAlertURL: null + rejectAlertURL: null + retries: 5 + timeout: 30000 + timeoutAlertURL: null + token: "6R0W53R135510" +tags: +- name: Management-REST-APIs diff --git a/api/v2/11.yml b/api/v2/11.yml new file mode 100644 index 0000000..d636a3d --- /dev/null +++ b/api/v2/11.yml @@ -0,0 +1,138 @@ +openapi: 3.0.0 +info: + title: Browserless API Documentation + version: v2.0.0 +servers: + - url: https://production-sfo.browserless.io + - url: https://production-lon.browserless.io + +paths: + /metrics: + get: + summary: Fetch metrics + description: Retrieve an array of session statistics. The data returned will have a maximum date of 1 week. + parameters: + - name: token + in: query + required: true + description: API key. + schema: + type: string + responses: + 200: + description: Array of session statistics + content: + application/json: + schema: + type: array + items: + type: object + properties: + error: + type: integer + maxConcurrent: + type: integer + queued: + type: integer + rejected: + type: integer + running: + type: integer + sessionTimes: + type: array + items: + type: integer + successful: + type: integer + timedout: + type: integer + unauthorized: + type: integer + unhealthy: + type: integer + maxTime: + type: integer + meanTime: + type: integer + minTime: + type: integer + totalTime: + type: integer + units: + type: integer + date: + type: integer + cpu: + type: number + memory: + type: number + example: + - error: 3 + maxConcurrent: 4 + queued: 0 + rejected: 0 + running: 3 + sessionTimes: [992, 1041, 802] + successful: 0 + timedout: 0 + unauthorized: 0 + unhealthy: 0 + maxTime: 1041 + meanTime: 945 + minTime: 802 + totalTime: 2835 + units: 3 + date: 1709134233732 + cpu: 0.024877870173220466 + memory: 0.7784158564199399 + + /metrics/total: + get: + summary: Fetch total metrics + description: This route will output a similar payload, but with the total stats of all sessions. + responses: + 200: + description: Total session statistics + content: + application/json: + schema: + type: object + properties: + error: + type: integer + maxConcurrent: + type: integer + queued: + type: integer + rejected: + type: integer + running: + type: integer + sessionTimes: + type: array + items: + type: integer + successful: + type: integer + timedout: + type: integer + unauthorized: + type: integer + unhealthy: + type: integer + maxTime: + type: integer + meanTime: + type: integer + minTime: + type: integer + totalTime: + type: integer + units: + type: integer + date: + type: integer + cpu: + type: number + memory: + type: number diff --git a/api/v2/2.yml b/api/v2/2.yml new file mode 100644 index 0000000..462412a --- /dev/null +++ b/api/v2/2.yml @@ -0,0 +1,81 @@ +openapi: 3.0.1 +info: + title: Browserless API + version: v2 +servers: + - url: 'https://production-sfo.browserless.io' + - url: 'https://production-lon.browserless.io' +paths: + /download: + post: + summary: Download file from Puppeteer script + operationId: download + description: Invoke Puppeteer script code and download any files created within the context of the browser. + requestBody: + required: true + content: + application/javascript: + schema: + type: string + example: | + export default function ({ page }){ + await page.evaluate(() => { + const json = { + ping: "pong", + rnd: [...Array(5)].map(() => Math.random()) + } + const jsonContent = `data:application/json,${JSON.stringify(json)}`; + const encodedUri = encodeURI(jsonContent); + const link = document.createElement('a'); + + link.setAttribute('href', encodedUri); + link.setAttribute('download', 'data.json'); + document.body.appendChild(link); + return link.click(); + }); + } + application/json: + schema: + type: object + properties: + code: + type: string + description: Custom download code + context: + type: object + description: Value used to pass context values and arguments to the `code` + properties: + url: + type: string + description: The URL to be used in the context + arrayLen: + type: integer + description: Length of the random array + required: + - code + - context + example: + code: "async function({page:t,context:a}){await t.evaluate(t=>{let a={url:t.url,ping:`pong`,rnd:[...Array(t.arrayLen)].map(()=>Math.random())},e=`data:application/json,${JSON.stringify(a)}`,n=encodeURI(e),r=document.createElement(`a`);return r.setAttribute(`href`,n),r.setAttribute(`download`,`data.json`),document.body.appendChild(r),r.click()},a)};" + context: + url: "https://browserless.io/" + arrayLen: 10 + responses: + 200: + description: File created by Puppeteer code + content: + application/octet-stream: + schema: + type: string + format: binary + 400: + description: Invalid request + 500: + description: Server error +components: + securitySchemes: + ApiKeyAuth: + type: apiKey + in: query + name: token +security: + - ApiKeyAuth: [] diff --git a/api/v2/3.yml b/api/v2/3.yml new file mode 100644 index 0000000..51bb3b1 --- /dev/null +++ b/api/v2/3.yml @@ -0,0 +1,68 @@ +openapi: 3.0.0 +info: + title: Browserless.io Function API + version: 2.0.0 +servers: +- url: https://production-sfo.browserless.io +- url: https://production-lon.browserless.io +paths: + /function: + post: + summary: Post custom code and context + description: > + The /function endpoint allows for POSTing of custom code and context to run them with. You can use Python, NodeJS or any other language that supports making HTTP requests. + requestBody: + required: true + content: + application/javascript: + schema: + properties: + function: + type: string + description: Puppeteer code function + example: | + export default async function ({ page }) { + const rndNumber = () => { + return Math.floor(Math.random() * (10**6 - 0)); + }; + + await page.goto("https://example.com/"); + const url = await page.title(); + const numbers = [...Array(5)].map(() => rndNumber()); + + return { + data: { + url, + numbers, + }, + // Make sure to match the appropriate content here + type: "application/json", + }; + } + application/json: + schema: + properties: + code: + type: string + description: String, required — custom function code. + example: "import{faker as a}from\"https://esm.sh/@faker-js/faker\";export default async function({context:o}){let t=a.internet,e=[...Array(o.len)].map(()=>({domain:t.domainName(),ip:t.ip(),mac:t.mac(),protocol:t.protocol()}));return{data:{domains:e,length:o.len},type:`application/json`}};" + context: + type: object + description: Object, optional — value used to pass context values and arguments to the `code` + example: "{ \"len\": 10 }" + responses: + '200': + description: Successful Response + content: + application/json: + schema: + type: object + properties: + data: + type: object + example: {"url":"Example Domain", "numbers": [854246,114512,212580,482122,107878]} + type: + type: string + example: "application/json" + '400': + description: Bad Request diff --git a/api/v2/4.yml b/api/v2/4.yml new file mode 100644 index 0000000..37cfea2 --- /dev/null +++ b/api/v2/4.yml @@ -0,0 +1,93 @@ +openapi: 3.0.0 +info: + title: PDF Generation API + version: v2 +servers: + - url: https://production-sfo.browserless.io + - url: https://production-lon.browserless.io +paths: + /pdf: + post: + description: Converts a webpage to pdf. + requestBody: + content: + application/json: + schema: + type: object + oneOf: + - properties: + url: + type: string + description: The URL to navigate page to. The url should include scheme, e.g. https://. + options: + $ref: '#/components/schemas/Options' + required: + - url + - properties: + html: + type: string + description: HTML content to render. + options: + $ref: '#/components/schemas/Options' + required: + - html + responses: + '200': + content: + application/pdf: + description: Successfully generated pdf. +components: + schemas: + Options: + type: object + properties: + displayHeaderFooter: + type: boolean + description: Display header and footer. + printBackground: + type: boolean + description: Print background graphics. + format: + type: string + description: Paper format. If set, takes priority over width or height options. Defaults to 'Letter'. + gotoOptions: + type: object + description: A set of key-value pairs to modify the default navigation behavior. + bestAttempt: + type: boolean + description: When async events fail or timeout, attempt to proceed. + waitForSelector: + type: object + description: An object describing desired selector and timeout attributes for waiting before proceed. + waitForEvent: + type: object + description: An object describing desired event and timeout attributes for waiting before proceed. + waitForFunction: + type: object + description: An object with js function and timeout attributes to be executed before proceed. + rejectResourceTypes: + type: array + items: + type: string + description: Block undesired content, resources. + rejectRequestPattern: + type: array + items: + type: string + description: Block undesired requests. + addScriptTag: + type: array + items: + type: object + properties: + url: { type: string } + content: { type: string } + description: Load additional script tags. + addStyleTag: + type: array + items: + type: object + properties: + url: { type: string } + content: { type: string } + description: Load additional style tags. diff --git a/api/v2/5.yml b/api/v2/5.yml new file mode 100644 index 0000000..8b47e41 --- /dev/null +++ b/api/v2/5.yml @@ -0,0 +1,98 @@ +openapi: 3.0.0 +info: + title: Browserless.io screenshot API + version: 2.0.0 +servers: + - url: https://production-sfo.browserless.io + - url: https://production-lon.browserless.io +paths: + /screenshot: + post: + operationId: getScreenshot + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: uri + options: + type: object + properties: + fullPage: + type: boolean + type: + type: string + enum: ["png", "jpg", "webp"] + addScriptTag: + type: array + items: + type: object + properties: + url: + type: string + content: + type: string + addStyleTag: + type: array + items: + type: object + properties: + url: + type: string + content: + type: string + rejectResourceTypes: + type: array + items: + type: string + rejectRequestPattern: + type: array + items: + type: string + gotoOptions: + type: object + properties: + waitUntil: + type: string + default: 'networkidle2' + bestAttempt: + type: boolean + waitForSelector: + type: object + properties: + selector: + type: string + timeout: + type: number + waitForEvent: + type: object + properties: + event: + type: string + timeout: + type: number + waitForFunction: + type: object + properties: + fn: + type: string + timeout: + type: number + responses: + 200: + description: Returns a screenshot of a webpage as a binary or base64 encoded image (png or jpg) + content: + application/json: + schema: + type: object + properties: + screenshot: + type: string + example: + screenshot: "Base64EncodedScreenshotData" + default: + description: An error occurred diff --git a/api/v2/6.yml b/api/v2/6.yml new file mode 100644 index 0000000..e7a7af7 --- /dev/null +++ b/api/v2/6.yml @@ -0,0 +1,88 @@ +openapi: 3.0.0 +info: + title: /unblock API + version: v2 +paths: + /unblock: + post: + summary: Unblock page + operationId: unblock + description: API designed to bypass bot detection mechanisms such as Cloudflare, Datadome and other passive CAPTCHAs. + parameters: + - in: query + name: token + schema: + type: string + description: Token to be used for authentication. + - in: query + name: proxy + schema: + type: string + description: The proxy type set for the request. + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UnblockRequest' + example: + url: 'https://example.com/' + browserWSEndpoint: false + cookies: false + content: true + screenshot: false + responses: + '200': + description: Request was successful + content: + application/json: + schema: + $ref: '#/components/schemas/UnblockResponse' + example: + browserWSEndpoint: 'wss://production-sfo.browserless.io/e/53616c7465645f5fa57aca44763bd816bb1aa1f1210ed871a908fd60235848ce6e4bcc0a8fcfe08c6d96eff8d68d556e/devtools/browser/646b292c-bd2a-4964-af18-9c1a6081c32e' + content: '...' + cookies: [] + screenshot: null + ttl: 60000 +components: + schemas: + UnblockRequest: + type: object + properties: + url: + type: string + description: URL of the site to be unblocked + browserWSEndpoint: + type: boolean + description: If set to true, a connection with the browser instance is created + cookies: + type: boolean + description: If set to true, cookies are included in the response + content: + type: boolean + description: If set to true, page HTML is included in the response + screenshot: + type: boolean + description: If set to true, screenshot of the page is included in the response + ttl: + type: integer + description: Duration before expiring the created endpoint, applicable only if browserWSEndpoint is true + UnblockResponse: + type: object + properties: + browserWSEndpoint: + type: string + description: Endpoint where a WebSocket can be created + content: + type: string + description: Entire HTML of the unblocked page + cookies: + type: array + items: + type: string + description: Cookies associated with the requested page + screenshot: + type: string + description: Base64 of the captured screenshot, if requested + ttl: + type: integer + description: Expiry of the generated endpoint diff --git a/api/v2/7.yml b/api/v2/7.yml new file mode 100644 index 0000000..c5061be --- /dev/null +++ b/api/v2/7.yml @@ -0,0 +1,124 @@ +openapi: "3.0.0" +info: + title: Browserless.io /scrape API + version: "2.0" +servers: + - url: https://production-sfo.browserless.io + - url: https://production-lon.browserless.io +paths: + /scrape: + post: + summary: Scrape web page + operationId: scrape + parameters: + - in: query + name: token + required: true + schema: + type: string + example: MY_API_TOKEN + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + url: + type: string + example: "https://browserless.io/" + elements: + type: array + items: + type: object + properties: + selector: + type: string + example: "h1" + gotoOptions: + type: object + properties: + timeout: + type: integer + example: 10000 + waitUntil: + type: string + example: "networkidle2" + waitForTimeout: + type: integer + example: 1000 + waitForSelector: + type: object + properties: + selector: + type: string + example: "h1" + timeout: + type: integer + example: 5000 + waitForFunction: + type: object + properties: + fn: + type: string + example: "async()=>{let t=await fetch('https://jsonplaceholder.typicode.com/todos/1'),e=await t.json();document.querySelector('h1').innerText=e.title}" + timeout: + type: integer + example: 5000 + waitForEvent: + type: object + properties: + event: + type: string + example: "fullscreenchange" + timeout: + type: integer + example: 5000 + responses: + "200": + description: Successful Response + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + properties: + results: + type: object + properties: + attributes: + type: array + items: + type: object + properties: + name: + type: string + example: "class" + value: + type: string + example: "..." + height: + type: integer + example: 120 + html: + type: string + example: "Headless browser automation, without the hosting headaches" + left: + type: integer + example: 32 + text: + type: string + example: "Headless browser automation, without the hosting headaches" + top: + type: integer + example: 196 + width: + type: integer + example: 736 + selector: + type: string + example: "h1" diff --git a/api/v2/8.yml b/api/v2/8.yml new file mode 100644 index 0000000..279458b --- /dev/null +++ b/api/v2/8.yml @@ -0,0 +1,54 @@ +openapi: 3.0.0 +info: + title: Browserless V2 API + description: A performance API to gather key metrics about a website's accessibility, best practices, performance, PWA information, and SEO. + version: 2.0.0 +servers: + - url: https://production-sfo.browserless.io + description: Browserless Production API SFO + - url: https://production-lon.browserless.io + description: Browserless Production API LON +paths: + /performance: + post: + description: Gather performance data of a site + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + url: + type: string + description: A valid URL to gather performance data from. + config: + type: object + description: Configurable settings for performance data gathering. + example: + url: https://example.com/ + responses: + "200": + description: Performance data successfully gathered + content: + application/json: + schema: + type: object + properties: + audits: + type: object + example: + audits: + "is-on-https": + title: "Uses HTTPS" + score: 1 + "viewport": + title: "Has a `` tag with `width` or `initial-scale`" + score: 1 + "first-contentful-paint": + score: 1 + displayValue: "0.8 s" + "400": + description: Bad request + "500": + description: Internal server error diff --git a/api/v2/9.yml b/api/v2/9.yml new file mode 100644 index 0000000..8bd9cd0 --- /dev/null +++ b/api/v2/9.yml @@ -0,0 +1,86 @@ +openapi: 3.0.0 +info: + title: Browserless API + version: v2 +paths: + /sessions: + get: + summary: Gather information about the currently running sessions + description: "This API is available only for dedicated and self-hosted accounts. Issue a `GET` request to `/sessions` to gather information regarding the running sessions." + servers: + - url: https://production-sfo.browserless.io + - url: https://production-lon.browserless.io + parameters: + - in: query + name: token + required: true + schema: + type: string + description: API token + responses: + 200: + description: Successful operation + content: + application/json: + schema: + type: array + items: + type: object + properties: + id: + type: string + initialConnectURL: + type: string + isTempDataDir: + type: boolean + launchOptions: + type: object + numbConnected: + type: integer + routePath: + type: array + items: + type: string + startedOn: + type: integer + ttl: + type: integer + userDataDir: + type: string + browser: + type: string + browserId: + type: string + killURL: + type: string + running: + type: boolean + timeAliveMs: + type: integer + type: + type: string + examples: + sessionInfo: + summary: Example of session info + value: + [ + { + "id": null, + "initialConnectURL": "http://production-sfo.browserless.io/firefox/playwright/?token=GOES-HERE", + "isTempDataDir": true, + "launchOptions": {}, + "numbConnected": 1, + "routePath": ["/firefox/playwright", "/firefox/playwright"], + "startedOn": 1709584439748, + "ttl": 0, + "userDataDir": null, + "browser": "FirefoxPlaywright", + "browserId": "d9a8570a73666d79d79ac23f07cf8966", + "killURL": null, + "running": true, + "timeAliveMs": 10118, + "type": "browser" + } + ] + 401: + description: Unauthorized. API key is missing or invalid. diff --git a/openapi.config.json b/openapi.config.json new file mode 100644 index 0000000..e1897bb --- /dev/null +++ b/openapi.config.json @@ -0,0 +1,35 @@ +{ + "inputs": [ + { + "inputFile": "./api/v2/2.yml" + }, + { + "inputFile": "./api/v2/3.yml" + }, + { + "inputFile": "./api/v2/4.yml" + }, + { + "inputFile": "./api/v2/5.yml" + }, + { + "inputFile": "./api/v2/6.yml" + }, + { + "inputFile": "./api/v2/7.yml" + }, + { + "inputFile": "./api/v2/8.yml" + }, + { + "inputFile": "./api/v2/9.yml" + }, + { + "inputFile": "./api/v2/10.yml" + }, + { + "inputFile": "./api/v2/11.yml" + } + ], + "output": "./openapi.yml" +} diff --git a/package.json b/package.json index 693cb3a..3cddb56 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,10 @@ "lintfix": "tslint --fix -p tsconfig.json -c tslint.json && eslint nodes credentials package.json --fix", "prepublishOnly": "npm run build && npm run lint -c .eslintrc.prepublish.js nodes credentials package.json", "gen:types": "ts-node ./scripts/gen-types.ts", - "test": "jest" + "test": "jest", + "merge:api": "npx openapi-merge-cli --config ./openapi.config.json", + "p2o": "p2o ./collection.json -f ./openapi.yml", + "codegen": "node ../../cli.js -o . -c nodes.config.js ./openapi.yml ../templates/n8n-nodes && pnpm lintfix && pnpm format --log-level=error" }, "files": [ "dist"