chrome-cdp-cli 2.0.4 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/ArgumentParser.js +172 -91
- package/dist/cli/CLIApplication.js +181 -57
- package/dist/cli/CommandRouter.js +98 -74
- package/dist/cli/CommandSchemaRegistry.js +506 -398
- package/dist/cli/EnhancedCLIInterface.js +2 -1
- package/dist/cli/HelpSystem.js +286 -256
- package/dist/handlers/ClickHandler.js +91 -27
- package/dist/handlers/InstallClaudeSkillHandler.js +220 -220
- package/dist/handlers/InstallCursorCommandHandler.js +60 -60
- package/dist/handlers/ListConsoleMessagesHandler.js +126 -178
- package/dist/handlers/ListNetworkRequestsHandler.js +128 -108
- package/dist/handlers/RestartProxyHandler.js +4 -4
- package/dist/handlers/TakeScreenshotHandler.js +70 -59
- package/dist/handlers/TakeSnapshotHandler.js +223 -165
- package/dist/handlers/index.js +0 -1
- package/dist/monitors/ConsoleMonitor.js +29 -0
- package/dist/monitors/NetworkMonitor.js +43 -19
- package/dist/proxy/server/CDPProxyServer.js +5 -1
- package/dist/proxy/server/CommandExecutionService.js +1 -1
- package/dist/proxy/server/ProxyAPIServer.js +11 -6
- package/package.json +3 -2
|
@@ -2,140 +2,160 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ListNetworkRequestsHandler = void 0;
|
|
4
4
|
const NetworkMonitor_1 = require("../monitors/NetworkMonitor");
|
|
5
|
-
const ProxyClient_1 = require("../client/ProxyClient");
|
|
6
5
|
class ListNetworkRequestsHandler {
|
|
7
6
|
constructor() {
|
|
8
|
-
this.name =
|
|
7
|
+
this.name = "network";
|
|
9
8
|
this.networkMonitor = null;
|
|
10
|
-
this.proxyClient = null;
|
|
11
9
|
}
|
|
12
10
|
async execute(client, args) {
|
|
13
11
|
try {
|
|
14
12
|
const params = args;
|
|
15
|
-
|
|
16
|
-
if (proxyResult) {
|
|
17
|
-
return proxyResult;
|
|
18
|
-
}
|
|
19
|
-
return await this.executeDirectCDP(client, params);
|
|
13
|
+
return await this.executeFollowMode(client, params);
|
|
20
14
|
}
|
|
21
15
|
catch (error) {
|
|
22
16
|
return {
|
|
23
17
|
success: false,
|
|
24
|
-
error: error instanceof Error ? error.message :
|
|
18
|
+
error: error instanceof Error ? error.message : "Unknown error occurred",
|
|
25
19
|
};
|
|
26
20
|
}
|
|
27
21
|
}
|
|
28
|
-
async
|
|
29
|
-
try {
|
|
30
|
-
if (!this.proxyClient) {
|
|
31
|
-
this.proxyClient = new ProxyClient_1.ProxyClient();
|
|
32
|
-
}
|
|
33
|
-
const isProxyAvailable = await this.proxyClient.isProxyAvailable();
|
|
34
|
-
if (!isProxyAvailable) {
|
|
35
|
-
const proxyStarted = await this.proxyClient.ensureProxyRunning();
|
|
36
|
-
if (!proxyStarted) {
|
|
37
|
-
console.warn('⚠️ Proxy server unavailable. Falling back to direct CDP connection.');
|
|
38
|
-
console.warn('⚠️ Note: Direct connection only captures NEW network requests, not historical data.');
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (!this.proxyClient.getConnectionId()) {
|
|
43
|
-
const host = params.host || 'localhost';
|
|
44
|
-
const port = params.port || 9222;
|
|
45
|
-
await this.proxyClient.connect(host, port, params.targetId);
|
|
46
|
-
}
|
|
47
|
-
const filter = params.filter ? {
|
|
48
|
-
methods: params.filter.methods,
|
|
49
|
-
urlPattern: params.filter.urlPattern,
|
|
50
|
-
statusCodes: params.filter.statusCodes,
|
|
51
|
-
maxRequests: params.latest ? 1 : params.filter.maxRequests,
|
|
52
|
-
startTime: params.filter.startTime,
|
|
53
|
-
endTime: params.filter.endTime,
|
|
54
|
-
} : params.latest ? { maxRequests: 1 } : undefined;
|
|
55
|
-
const requests = await this.proxyClient.getNetworkRequests(filter);
|
|
56
|
-
if (params.latest) {
|
|
57
|
-
const latestRequest = requests.length > 0 ? requests[requests.length - 1] : null;
|
|
58
|
-
if (!latestRequest) {
|
|
59
|
-
return {
|
|
60
|
-
success: true,
|
|
61
|
-
data: null,
|
|
62
|
-
dataSource: 'proxy',
|
|
63
|
-
hasHistoricalData: true
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
return {
|
|
67
|
-
success: true,
|
|
68
|
-
data: latestRequest,
|
|
69
|
-
dataSource: 'proxy',
|
|
70
|
-
hasHistoricalData: true
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
return {
|
|
74
|
-
success: true,
|
|
75
|
-
data: {
|
|
76
|
-
requests,
|
|
77
|
-
count: requests.length,
|
|
78
|
-
isMonitoring: true
|
|
79
|
-
},
|
|
80
|
-
dataSource: 'proxy',
|
|
81
|
-
hasHistoricalData: true
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
console.warn('⚠️ Proxy execution failed, falling back to direct CDP:', error instanceof Error ? error.message : error);
|
|
86
|
-
console.warn('⚠️ Note: Direct connection only captures NEW network requests, not historical data.');
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
async executeDirectCDP(client, params) {
|
|
22
|
+
async executeFollowMode(client, params) {
|
|
91
23
|
if (!this.networkMonitor) {
|
|
92
24
|
this.networkMonitor = new NetworkMonitor_1.NetworkMonitor(client);
|
|
93
25
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
} : undefined;
|
|
105
|
-
if (params.latest) {
|
|
106
|
-
const latestRequest = this.networkMonitor.getLatestRequest(filter);
|
|
107
|
-
if (!latestRequest) {
|
|
108
|
-
return {
|
|
109
|
-
success: true,
|
|
110
|
-
data: null,
|
|
111
|
-
dataSource: 'direct',
|
|
112
|
-
hasHistoricalData: false
|
|
113
|
-
};
|
|
26
|
+
await this.networkMonitor.startMonitoring();
|
|
27
|
+
const methods = this.parseList(params.methods);
|
|
28
|
+
const statusCodes = this.parseList(params.statusCodes)
|
|
29
|
+
.map(Number)
|
|
30
|
+
.filter((n) => !isNaN(n));
|
|
31
|
+
const urlPattern = params.urlPattern;
|
|
32
|
+
const outputFormat = params.format || "text";
|
|
33
|
+
const requestCallback = (request) => {
|
|
34
|
+
if (!this.shouldOutputRequest(request, methods, urlPattern, statusCodes)) {
|
|
35
|
+
return;
|
|
114
36
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
37
|
+
this.outputRequest(request, outputFormat);
|
|
38
|
+
};
|
|
39
|
+
this.networkMonitor.onRequest(requestCallback);
|
|
40
|
+
let isShuttingDown = false;
|
|
41
|
+
const cleanup = async () => {
|
|
42
|
+
if (isShuttingDown)
|
|
43
|
+
return;
|
|
44
|
+
isShuttingDown = true;
|
|
45
|
+
this.networkMonitor?.offRequest(requestCallback);
|
|
46
|
+
await this.networkMonitor?.stopMonitoring();
|
|
47
|
+
};
|
|
48
|
+
const signalHandler = async () => {
|
|
49
|
+
process.stderr.write("\n");
|
|
50
|
+
await cleanup();
|
|
51
|
+
process.exit(0);
|
|
52
|
+
};
|
|
53
|
+
process.removeAllListeners("SIGINT");
|
|
54
|
+
process.removeAllListeners("SIGTERM");
|
|
55
|
+
process.on("SIGINT", signalHandler);
|
|
56
|
+
process.on("SIGTERM", signalHandler);
|
|
57
|
+
if (outputFormat === "text") {
|
|
58
|
+
console.log("Following network requests (press Ctrl+C to stop)...\n");
|
|
121
59
|
}
|
|
122
|
-
const requests = this.networkMonitor.getRequests(filter);
|
|
123
60
|
return {
|
|
124
61
|
success: true,
|
|
125
62
|
data: {
|
|
126
|
-
requests,
|
|
127
|
-
|
|
128
|
-
isMonitoring: this.networkMonitor.isActive()
|
|
63
|
+
message: "Following network requests in real-time. Press Ctrl+C to stop.",
|
|
64
|
+
isLongRunning: true,
|
|
129
65
|
},
|
|
130
|
-
|
|
131
|
-
hasHistoricalData: false
|
|
66
|
+
isLongRunning: true,
|
|
132
67
|
};
|
|
133
68
|
}
|
|
134
|
-
|
|
135
|
-
|
|
69
|
+
parseList(value) {
|
|
70
|
+
if (!value)
|
|
71
|
+
return [];
|
|
72
|
+
if (Array.isArray(value))
|
|
73
|
+
return value;
|
|
74
|
+
return value
|
|
75
|
+
.split(",")
|
|
76
|
+
.map((s) => s.trim())
|
|
77
|
+
.filter(Boolean);
|
|
78
|
+
}
|
|
79
|
+
shouldOutputRequest(request, methods, urlPattern, statusCodes) {
|
|
80
|
+
if (methods.length > 0 &&
|
|
81
|
+
!methods
|
|
82
|
+
.map((m) => m.toUpperCase())
|
|
83
|
+
.includes(request.method.toUpperCase())) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
if (urlPattern) {
|
|
87
|
+
const pattern = new RegExp(urlPattern, "i");
|
|
88
|
+
if (!pattern.test(request.url))
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
if (statusCodes.length > 0 &&
|
|
92
|
+
request.status !== undefined &&
|
|
93
|
+
!statusCodes.includes(request.status)) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
outputRequest(request, format) {
|
|
99
|
+
const status = request.status ?? "???";
|
|
100
|
+
const method = request.method.toUpperCase().padEnd(7);
|
|
101
|
+
const time = new Date(request.timestamp).toISOString();
|
|
102
|
+
switch (format) {
|
|
103
|
+
case "json":
|
|
104
|
+
console.log(JSON.stringify({
|
|
105
|
+
method: request.method,
|
|
106
|
+
url: request.url,
|
|
107
|
+
status: request.status,
|
|
108
|
+
timestamp: request.timestamp,
|
|
109
|
+
}));
|
|
110
|
+
break;
|
|
111
|
+
case "pretty": {
|
|
112
|
+
const statusColor = this.getStatusColor(request.status);
|
|
113
|
+
console.log(`[${time}] ${method} ${statusColor}${status}\x1b[0m ${request.url}`);
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
case "text":
|
|
117
|
+
default:
|
|
118
|
+
console.log(`[${time}] ${method} ${status} ${request.url}`);
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
getStatusColor(status) {
|
|
123
|
+
if (status === undefined || status === 0)
|
|
124
|
+
return "\x1b[31m";
|
|
125
|
+
if (status >= 500)
|
|
126
|
+
return "\x1b[31m";
|
|
127
|
+
if (status >= 400)
|
|
128
|
+
return "\x1b[33m";
|
|
129
|
+
if (status >= 300)
|
|
130
|
+
return "\x1b[36m";
|
|
131
|
+
return "\x1b[32m";
|
|
136
132
|
}
|
|
137
|
-
|
|
138
|
-
|
|
133
|
+
getHelp() {
|
|
134
|
+
return `network - Follow network requests in real-time
|
|
135
|
+
|
|
136
|
+
Usage:
|
|
137
|
+
cdp network [options]
|
|
138
|
+
|
|
139
|
+
Options:
|
|
140
|
+
--methods <methods> Filter by HTTP methods (comma-separated: GET,POST,PUT,DELETE,...)
|
|
141
|
+
--urlPattern <pattern> Filter by URL pattern (regex, case-insensitive)
|
|
142
|
+
--statusCodes <codes> Filter by HTTP status codes (comma-separated: 200,404,500)
|
|
143
|
+
--format <format> Output format: text, json, or pretty (default: text)
|
|
144
|
+
-f, --follow Alias flag (follow mode is always active)
|
|
145
|
+
|
|
146
|
+
Examples:
|
|
147
|
+
cdp network # Follow all network requests
|
|
148
|
+
cdp network --methods POST,PUT # Follow only POST and PUT requests
|
|
149
|
+
cdp network --urlPattern "/api/" # Follow requests matching /\\/api\\//i
|
|
150
|
+
cdp network --statusCodes 404,500 # Follow requests with error status
|
|
151
|
+
cdp network --format json # Output as JSON (one object per line)
|
|
152
|
+
cdp network --format pretty # Colorized output
|
|
153
|
+
cdp network --methods GET --urlPattern "/api" # Combined filters
|
|
154
|
+
|
|
155
|
+
Note:
|
|
156
|
+
This command runs continuously and streams network requests in real-time.
|
|
157
|
+
Each entry is printed when the request fully completes (or fails).
|
|
158
|
+
Press Ctrl+C to stop. No background process is required.`;
|
|
139
159
|
}
|
|
140
160
|
}
|
|
141
161
|
exports.ListNetworkRequestsHandler = ListNetworkRequestsHandler;
|
|
@@ -61,8 +61,8 @@ class RestartProxyHandler {
|
|
|
61
61
|
restart - Restart the proxy server process
|
|
62
62
|
|
|
63
63
|
Usage:
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
cdp restart
|
|
65
|
+
cdp restart --force
|
|
66
66
|
|
|
67
67
|
Description:
|
|
68
68
|
Restarts the proxy server process. This will:
|
|
@@ -82,10 +82,10 @@ Options:
|
|
|
82
82
|
|
|
83
83
|
Examples:
|
|
84
84
|
# Restart the proxy server
|
|
85
|
-
|
|
85
|
+
cdp restart
|
|
86
86
|
|
|
87
87
|
# Force restart even if proxy is healthy
|
|
88
|
-
|
|
88
|
+
cdp restart --force
|
|
89
89
|
|
|
90
90
|
Note:
|
|
91
91
|
- Restarting the proxy will clear all stored console messages and network requests
|
|
@@ -5,18 +5,27 @@ const fs_1 = require("fs");
|
|
|
5
5
|
const path_1 = require("path");
|
|
6
6
|
class TakeScreenshotHandler {
|
|
7
7
|
constructor() {
|
|
8
|
-
this.name =
|
|
8
|
+
this.name = "screenshot";
|
|
9
9
|
}
|
|
10
10
|
async execute(client, args) {
|
|
11
11
|
const screenshotArgs = args;
|
|
12
12
|
try {
|
|
13
|
-
|
|
13
|
+
if (!screenshotArgs.filename && process.stdout.isTTY) {
|
|
14
|
+
process.stderr.write("Error: Binary output to terminal detected.\n" +
|
|
15
|
+
"Use --filename <path> to save to a file, or redirect: cdp screenshot > page.png\n");
|
|
16
|
+
return {
|
|
17
|
+
success: false,
|
|
18
|
+
error: "Binary output to terminal detected. Use --filename or redirect output.",
|
|
19
|
+
exitCode: 1,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
await client.send("Page.enable");
|
|
14
23
|
const params = this.buildScreenshotParams(screenshotArgs);
|
|
15
|
-
const response = await client.send(
|
|
24
|
+
const response = (await client.send("Page.captureScreenshot", params));
|
|
16
25
|
if (!response || !response.data) {
|
|
17
26
|
return {
|
|
18
27
|
success: false,
|
|
19
|
-
error:
|
|
28
|
+
error: "Failed to capture screenshot: empty response",
|
|
20
29
|
};
|
|
21
30
|
}
|
|
22
31
|
if (screenshotArgs.filename) {
|
|
@@ -26,31 +35,30 @@ class TakeScreenshotHandler {
|
|
|
26
35
|
data: {
|
|
27
36
|
message: `Screenshot saved to ${screenshotArgs.filename}`,
|
|
28
37
|
filename: screenshotArgs.filename,
|
|
29
|
-
|
|
30
|
-
}
|
|
38
|
+
imageFormat: screenshotArgs.imageFormat || "png",
|
|
39
|
+
},
|
|
31
40
|
};
|
|
32
41
|
}
|
|
42
|
+
process.stdout.write(Buffer.from(response.data, "base64"));
|
|
33
43
|
return {
|
|
34
44
|
success: true,
|
|
35
|
-
data:
|
|
36
|
-
|
|
37
|
-
format: screenshotArgs.format || 'png'
|
|
38
|
-
}
|
|
45
|
+
data: null,
|
|
46
|
+
_rawOutput: true,
|
|
39
47
|
};
|
|
40
48
|
}
|
|
41
49
|
catch (error) {
|
|
42
50
|
return {
|
|
43
51
|
success: false,
|
|
44
|
-
error: error instanceof Error ? error.message : String(error)
|
|
52
|
+
error: error instanceof Error ? error.message : String(error),
|
|
45
53
|
};
|
|
46
54
|
}
|
|
47
55
|
}
|
|
48
56
|
buildScreenshotParams(args) {
|
|
49
57
|
const params = {};
|
|
50
|
-
params.format = args.
|
|
51
|
-
if (args.
|
|
58
|
+
params.format = args.imageFormat || "png";
|
|
59
|
+
if (args.imageFormat === "jpeg" && args.quality !== undefined) {
|
|
52
60
|
if (args.quality < 0 || args.quality > 100) {
|
|
53
|
-
throw new Error(
|
|
61
|
+
throw new Error("JPEG quality must be between 0 and 100");
|
|
54
62
|
}
|
|
55
63
|
params.quality = args.quality;
|
|
56
64
|
}
|
|
@@ -60,7 +68,7 @@ class TakeScreenshotHandler {
|
|
|
60
68
|
y: args.clip.y,
|
|
61
69
|
width: args.clip.width,
|
|
62
70
|
height: args.clip.height,
|
|
63
|
-
scale: args.clip.scale || 1
|
|
71
|
+
scale: args.clip.scale || 1,
|
|
64
72
|
};
|
|
65
73
|
}
|
|
66
74
|
if (args.width || args.height) {
|
|
@@ -74,7 +82,7 @@ class TakeScreenshotHandler {
|
|
|
74
82
|
try {
|
|
75
83
|
const dir = (0, path_1.dirname)(filename);
|
|
76
84
|
await fs_1.promises.mkdir(dir, { recursive: true });
|
|
77
|
-
const buffer = Buffer.from(base64Data,
|
|
85
|
+
const buffer = Buffer.from(base64Data, "base64");
|
|
78
86
|
await fs_1.promises.writeFile(filename, buffer);
|
|
79
87
|
}
|
|
80
88
|
catch (error) {
|
|
@@ -82,88 +90,91 @@ class TakeScreenshotHandler {
|
|
|
82
90
|
}
|
|
83
91
|
}
|
|
84
92
|
validateArgs(args) {
|
|
85
|
-
if (typeof args !==
|
|
93
|
+
if (typeof args !== "object" || args === null) {
|
|
86
94
|
return false;
|
|
87
95
|
}
|
|
88
96
|
const screenshotArgs = args;
|
|
89
|
-
if (screenshotArgs.filename !== undefined &&
|
|
97
|
+
if (screenshotArgs.filename !== undefined &&
|
|
98
|
+
typeof screenshotArgs.filename !== "string") {
|
|
90
99
|
return false;
|
|
91
100
|
}
|
|
92
|
-
if (screenshotArgs.width !== undefined &&
|
|
101
|
+
if (screenshotArgs.width !== undefined &&
|
|
102
|
+
(typeof screenshotArgs.width !== "number" || screenshotArgs.width <= 0)) {
|
|
93
103
|
return false;
|
|
94
104
|
}
|
|
95
|
-
if (screenshotArgs.height !== undefined &&
|
|
105
|
+
if (screenshotArgs.height !== undefined &&
|
|
106
|
+
(typeof screenshotArgs.height !== "number" || screenshotArgs.height <= 0)) {
|
|
96
107
|
return false;
|
|
97
108
|
}
|
|
98
|
-
if (screenshotArgs.
|
|
109
|
+
if (screenshotArgs.imageFormat !== undefined &&
|
|
110
|
+
!["png", "jpeg"].includes(screenshotArgs.imageFormat)) {
|
|
99
111
|
return false;
|
|
100
112
|
}
|
|
101
113
|
if (screenshotArgs.quality !== undefined) {
|
|
102
|
-
if (typeof screenshotArgs.quality !==
|
|
114
|
+
if (typeof screenshotArgs.quality !== "number" ||
|
|
115
|
+
screenshotArgs.quality < 0 ||
|
|
116
|
+
screenshotArgs.quality > 100) {
|
|
103
117
|
return false;
|
|
104
118
|
}
|
|
105
119
|
}
|
|
106
|
-
if (screenshotArgs.fullPage !== undefined &&
|
|
120
|
+
if (screenshotArgs.fullPage !== undefined &&
|
|
121
|
+
typeof screenshotArgs.fullPage !== "boolean") {
|
|
107
122
|
return false;
|
|
108
123
|
}
|
|
109
124
|
if (screenshotArgs.clip !== undefined) {
|
|
110
125
|
const clip = screenshotArgs.clip;
|
|
111
|
-
if (typeof clip !==
|
|
126
|
+
if (typeof clip !== "object" || clip === null) {
|
|
112
127
|
return false;
|
|
113
128
|
}
|
|
114
|
-
if (typeof clip.x !==
|
|
115
|
-
typeof clip.
|
|
129
|
+
if (typeof clip.x !== "number" ||
|
|
130
|
+
typeof clip.y !== "number" ||
|
|
131
|
+
typeof clip.width !== "number" ||
|
|
132
|
+
typeof clip.height !== "number") {
|
|
116
133
|
return false;
|
|
117
134
|
}
|
|
118
135
|
if (clip.width <= 0 || clip.height <= 0) {
|
|
119
136
|
return false;
|
|
120
137
|
}
|
|
121
|
-
if (clip.scale !== undefined &&
|
|
138
|
+
if (clip.scale !== undefined &&
|
|
139
|
+
(typeof clip.scale !== "number" || clip.scale <= 0)) {
|
|
122
140
|
return false;
|
|
123
141
|
}
|
|
124
142
|
}
|
|
125
143
|
return true;
|
|
126
144
|
}
|
|
127
145
|
getHelp() {
|
|
128
|
-
return `
|
|
129
|
-
screenshot - Capture a screenshot of the current page
|
|
146
|
+
return `screenshot - Capture a screenshot of the current page
|
|
130
147
|
|
|
131
148
|
Usage:
|
|
132
|
-
screenshot
|
|
133
|
-
screenshot --filename
|
|
134
|
-
screenshot
|
|
135
|
-
screenshot --format jpeg --quality 80 --filename compressed.jpg
|
|
136
|
-
screenshot --full-page --filename full-page.png
|
|
149
|
+
cdp screenshot # Output PNG binary to stdout
|
|
150
|
+
cdp screenshot --filename page.png # Save to file
|
|
151
|
+
cdp screenshot > page.png # Pipe binary to file
|
|
137
152
|
|
|
138
153
|
Arguments:
|
|
139
|
-
--filename <path>
|
|
140
|
-
--width <pixels>
|
|
141
|
-
--height <pixels>
|
|
142
|
-
--format <png|jpeg>
|
|
143
|
-
--quality <1-100>
|
|
144
|
-
--full-page
|
|
145
|
-
--clip-x <pixels>
|
|
146
|
-
--clip-y <pixels>
|
|
147
|
-
--clip-width <pixels>
|
|
148
|
-
--clip-height <pixels>
|
|
149
|
-
--clip-scale <number>
|
|
154
|
+
--filename <path> Output filename (if omitted, binary is written to stdout)
|
|
155
|
+
--width <pixels> Screenshot width
|
|
156
|
+
--height <pixels> Screenshot height
|
|
157
|
+
--image-format <png|jpeg> Image encoding format (default: png)
|
|
158
|
+
--quality <1-100> JPEG quality (only for jpeg format)
|
|
159
|
+
--full-page Capture full page beyond viewport (default: false)
|
|
160
|
+
--clip-x <pixels> Clip rectangle X coordinate
|
|
161
|
+
--clip-y <pixels> Clip rectangle Y coordinate
|
|
162
|
+
--clip-width <pixels> Clip rectangle width
|
|
163
|
+
--clip-height <pixels> Clip rectangle height
|
|
164
|
+
--clip-scale <number> Clip rectangle scale factor
|
|
150
165
|
|
|
151
166
|
Examples:
|
|
152
|
-
|
|
153
|
-
screenshot
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
screenshot --
|
|
157
|
-
|
|
158
|
-
# Full page screenshot
|
|
159
|
-
screenshot --full-page --filename full-page.png
|
|
160
|
-
|
|
161
|
-
# Clipped screenshot
|
|
162
|
-
screenshot --clip-x 100 --clip-y 100 --clip-width 800 --clip-height 600 --filename clipped.png
|
|
167
|
+
cdp screenshot --filename page.png
|
|
168
|
+
cdp screenshot > page.png
|
|
169
|
+
cdp screenshot --image-format jpeg --quality 90 --filename page.jpg
|
|
170
|
+
cdp screenshot --full-page --filename full-page.png
|
|
171
|
+
cdp screenshot --clip-x 100 --clip-y 100 --clip-width 800 --clip-height 600 --filename clipped.png
|
|
163
172
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
173
|
+
Note:
|
|
174
|
+
When no --filename is given, raw binary image data is written to stdout.
|
|
175
|
+
Redirecting to a file (> page.png) or piping is the intended usage.
|
|
176
|
+
Running without redirection in a terminal will show a warning and exit.
|
|
177
|
+
The global --format flag has no effect on screenshot output.`;
|
|
167
178
|
}
|
|
168
179
|
}
|
|
169
180
|
exports.TakeScreenshotHandler = TakeScreenshotHandler;
|