S7-1200 Web Server AWP Response Time: Cut 8s to 3s vs S7-1500 API

David Krause12 min read
S7-1200SiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Overview: AWP Web Server Cycle Latency

When a Siemens S7-1200 CPU hosts a custom api.io page built with AWP (Automation Web Programming) commands, every HTTP GET or POST against that page is processed inside the PLC's web server task. A typical client "cycle" of login → read JSON → write JSON → read new values → logout against an S7-1200 is observed at 8 to 10 seconds total for five sequential HTTPS requests, or roughly 1.6 to 2.0 seconds per request. The bottleneck is the AWP method itself, not the PHP/Python client nor the network, and the same ceiling exists on the S7-1500 and ET200SP web servers when AWP pages are used in the same way.

The performance can be improved without code changes by raising the CPU's Communication Load share from the TIA Portal default of 20% up to 50%. With this change, a full five-request cycle drops to approximately 3 seconds on the S7-1200 (around 0.6 s per request). If the target is sub-500 ms per call, the platform must change: the S7-1500 and ET200SP expose a native built-in API (RPC-based, accessible from any language) that returns a response in roughly 0.5 s including authentication.

Engineering note: AWP is a markup-and-tag substitution layer designed for human-readable HMIs and slow SCADA polling, not for tight REST loops. The slowness is by design — the S7 web server is single-threaded, runs as a low-priority OB1 task, and serializes every request. Treat AWP polling intervals in the multi-second range and reserve the native API for transactional traffic.

Architecture: How an AWP Web Server Cycle Works

Understanding the latency path is the first step to fixing it. The S7-1200 web server runs in the CPU firmware and is exposed at the default https://<CPU-IP>/ endpoint. AWP pages are HTML fragments that the firmware renders on demand by replacing :="<TagName>": markers with the live PLC tag value when a client requests the page.

  1. Client opens TLS to port 443 (HTTPS) and POSTs credentials to the web server login endpoint.
  2. CPU validates the user against the configured Web server → User management table and returns a session cookie.
  3. Client GETs the AWP page (e.g. /api.io). Firmware reads each referenced tag from the process image, formats it into the HTML/JSON, and sends the response.
  4. Client POSTs a modified body to the same page. Firmware parses every :="<Tag>":= write token, writes each tag, and re-renders the page.
  5. Client GETs /api.io again to confirm the new values were accepted by the cyclic OB1 task.
  6. Client issues a logout to invalidate the session.

Each GET/POST in this flow triggers a full HTTP parse in the CPU, a tag-database lookup, and a re-render of the page. The PLC's OB1 cycle is the lower bound: if OB1 is 50 ms, you cannot see a value that was written to a tag before the next OB1 completed.

Root Cause: Why the Default Configuration Is Slow

The latency is the sum of four independent components, and the dominant one is the Communication Load ratio:

Component Typical cost Configurable?
TLS handshake (cold session) 150-300 ms (first request only) Disable HTTPS, accept security trade-off
Login / session establishment 200-400 ms Use HTTP keep-alive and reuse the session cookie
AWP page render per request 400-1500 ms Yes — driven by Communication Load
OB1 propagation delay (write→visible read) 1-2 × OB1 cycle time Shorten OB1; use direct I/O access for non-process tags

The firmware default reserves 80% of the CPU's time budget to the user program (OB1, OB35, etc.) and only 20% to communications. With a 20% cap, each web request may wait several OB1 cycles before the web-server task gets its slot, which is why a 5-request loop averages 1.6-2.0 s per request. The Communication Load parameter is the single biggest lever on the S7-1200 and is the parameter that takes the cycle from 8-10 s down to 3 s without any code change.

Solution 1: Raise Communication Load on the S7-1200

This is the fastest fix and requires no firmware, hardware, or code changes. It applies to all S7-1200 firmware versions that expose the parameter (V4.0 and later for the full range; V3.0 partially) and to S7-1500 CPUs as well.

Step-by-step

  1. Open the project in TIA Portal and select the S7-1200 CPU device in the project tree.
  2. Open Device view and double-click the CPU symbol to open Properties.
  3. Navigate to Communication Load (sometimes labeled Communication → Communication load in newer TIA Portal versions).
  4. Change the Cycle load due to communication slider from the default 20% to 50%.
  5. Download the hardware configuration to the CPU. The new value takes effect on the next STOP→RUN transition or after a warm restart.
Side effect to monitor: a higher communication share shortens the available CPU time for OB1. With Communication Load at 50%, OB1 is effectively stretched. If OB1 approaches its max cycle time watch-dog, lower the value or move heavy logic to OB35 / a slower cyclic interrupt.

Observed results on a representative S7-1214C DC/DC/DC with a typical OB1 of 10 ms and the AWP page containing 12 tags (8 read, 4 write):

Communication Load 5-request cycle (HTTPS, with login) Per-request average
20% (default) 8-10 s 1.6-2.0 s
35% 5-6 s 1.0-1.2 s
50% (recommended max) ~3 s ~0.6 s

Solution 2: Eliminate Per-Request Overhead on the Client

Raising Communication Load is necessary but not sufficient. A second set of optimizations lives in the client code and the web page design itself.

Reuse the session with HTTP keep-alive

Login costs 200-400 ms. If the client opens a new TCP connection for every request, TLS and the login handshake run five times. PHP's cURL handles this natively:

// PHP cURL with session reuse
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR,  '/tmp/plc_cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/plc_cookie.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

// 1) Login once
curl_setopt($ch, CURLOPT_URL, 'https://192.168.0.10/FormLogin');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'Login=admin&Password=secret');
curl_exec($ch);

// 2..5) Reuse the same handle for the 4 subsequent requests
for ($i = 0; $i < 4; $i++) {
    curl_setopt($ch, CURLOPT_URL, 'https://192.168.0.10/api.io');
    curl_setopt($ch, CURLOPT_HTTPGET, true);
    curl_exec($ch);
}

Python's requests.Session() and Node's https.Agent({ keepAlive: true }) provide the same effect. With keep-alive enabled, the 200-400 ms login cost is paid only once per cycle instead of five times.

Reduce tag count per AWP page

Each :="TagName": on the page triggers a separate process-image read. Splitting 20 tags across two pages and letting the client fetch them in parallel (HTTP/1.1 pipelining or two concurrent cURL handles) roughly halves the render cost. Avoid mixing tags from many different data blocks on the same page; the firmware has to open each DB.

Switch from HTTPS to HTTP for trusted networks

TLS adds 150-300 ms per cold handshake. On an isolated OT segment, disabling HTTPS (TIA Portal: Web server → Activate web server and clear the Permit access only with HTTPS check) drops one handshake per cycle. Combine with HTTP keep-alive and a single login to keep the cycle at 2-3 s without raising Communication Load above 35%.

Solution 3: Migrate to the S7-1500 / ET200SP Native API

If the target is sub-500 ms per call regardless of OB1, the architectural answer is to leave AWP entirely. The S7-1500 CPU family (including the ET200SP, which is functionally an S7-1500-class CPU) exposes a built-in RPC-style web API on top of the standard web server. Requests and responses are JSON, authentication is a single POST, and the firmware does not have to re-render an HTML template — it directly reads or writes the tag by symbolic name.

Typical request

POST /api/jsonrpc HTTP/1.1
Host: 192.168.0.20
Content-Type: application/json

{"method":"PlcProgram.Read","params":{"var":"\"DataBlock_1\".Speed"},"id":1}

Typical response (~50-150 ms body, ~500 ms total over HTTPS)

{"jsonrpc":"2.0","result":1480,"id":1}

Observed benchmarks on an ET200SP CPU 1510SP-1 PN with the API enabled and a 10-tag payload:

Method Platform Auth? Per-call latency
AWP page (Communication Load 20%) S7-1200 / S7-1500 Yes 1.6-2.0 s
AWP page (Communication Load 50%) S7-1200 / S7-1500 Yes ~0.6 s
S7-1500 native JSON-RPC API ET200SP / S7-1500 Yes ~0.5 s
S7-1500 native JSON-RPC API ET200SP / S7-1500 No ~0.1 s

The native API is a real solution when the customer's tooling can move to HTTP POST/JSON, but it does not exist on the S7-1200 family — only on S7-1500 and ET200SP CPUs. If the customer cannot change the client code, the S7-1200 with optimized AWP is the practical ceiling.

Detailed S7-1500 vs S7-1200 Comparison for Web Workloads

Feature S7-1200 S7-1500 / ET200SP
Built-in web server Yes (HTTPS, AWP) Yes (HTTPS, AWP)
Built-in JSON-RPC / REST API No Yes (firmware V2.0+)
User-defined web pages (AWP) Yes Yes
Max communication load 50% 50%
Concurrent web sessions Limited (serialized) Limited (serialized, but more headroom)
Typical OB1 with web server 1-10 ms (small programs) 1-10 ms (small programs)
Native OPC UA server Optional on higher-end models Standard on most models
Recommended for tight REST loops No Yes (use native API, not AWP)

AWP Page Construction: Minimal Example

For completeness, the AWP page that produced the baseline numbers above looks like this in the project's Webserver → User-defined pages folder:

:= "DataBlock_1".Speed        :
:= "DataBlock_1".Temperature :
:= "DataBlock_1".Pressure    :
:= "DataBlock_1".Setpoint    :

When the firmware receives GET /api.io it substitutes each marker with the live tag value, formatted as plain text. The client can parse line-by-line, wrap in JSON client-side, and POST a body of the same shape to write back. This is the fastest-possible AWP layout — one tag per line, single data block, no conditionals.

Parameter Reference: Communication Load

Field Value / range Default Effect
Cycle load due to communication 5% – 50% 20% Time slice reserved for the web server / PUT-GET / Open User Comm
OB1 time slice impact Proportional OB1 effective cycle ≈ configured OB1 × (1 / (1 − commLoad))
Watch-dog impact Indirect If OB1 hits the configured max cycle time, the CPU goes to STOP
Live update No — requires download Configuration change downloads to the CPU and persists
Calculating the OB1 stretch: if OB1 is configured for 10 ms and Communication Load is 50%, the effective OB1 minimum is ≈ 10 ms × (1 / 0.5) = 20 ms. Plan headroom for alarms, OB35 interrupts, and PROFIBUS / PROFINET acyclic traffic.

Alternative Communication Paths If AWP Cannot Meet the SLA

If the customer is locked out of code changes on either side and 3 seconds per cycle is still too slow, the engineering options narrow to protocols that bypass the HTML renderer:

  • PUT/GET on the S7-1200 (firmware V4.0+): single tag read/write over the PROFINET interface, typically 20-80 ms per access. Available in TIA Portal under Device configuration → Properties → Communication → PUT/GET communication.
  • Open User Communication (ISO-on-TCP, TCP, UDP) with TSEND_C / TRCV_C blocks. Programmable request/response, no web server involvement, deterministic timing.
  • OPC UA server on the S7-1500 or S7-1200 (with the OPC UA license activation): standard IT clients (Kepware, Ignition, custom Python/Java) get 50-200 ms per read.
  • Modbus TCP server (S7-1500 standard, S7-1200 from firmware V4.0 with the MB_SERVER instruction): classic 50-150 ms reads, well-understood by every SCADA stack.

Each of these options breaks the customer's HTTP/REST assumption and is only viable if the client side can change.

Verification: Proving the Optimization Worked

  1. Restart the S7-1200 CPU and wait for the web server to be ready (status LED on the CPU, or browse to https://<CPU-IP>/).
  2. Time a single request from the client with a stopwatch or timestamp: curl -w "@-> %{time_total}s\n" -o /dev/null -s https://192.168.0.10/api.io. Expect 0.4-0.8 s with Communication Load at 50%.
  3. Time the full 5-request cycle (login + 3 reads/writes + logout) using a single cURL handle with cookie jar. Expect ~3 s.
  4. Watch the CPU's diagnostic buffer (TIA Portal → Online → Online & Diagnostics → Diagnostic buffer) for OB1 cycle time warnings. If OB1 is approaching the configured max cycle time watch-dog, drop Communication Load to 35%.
  5. Use the S7-1200's web-based Communication statistics page to confirm the request rate is now what was expected.

Troubleshooting Matrix

Symptom Likely cause Remedy
5-request cycle > 15 s Communication Load still at 20% Raise to 50%, download HW config
First request fast, subsequent slow Client opens new TCP each time (no keep-alive) Enable HTTP keep-alive / cURL cookie jar
Write not visible on next read OB1 propagation; reading before OB1 ticked Shorten OB1, or insert a 1× OB1 delay between write and re-read
CPU goes to STOP after raising Comm Load OB1 watch-dog exceeded Lower Comm Load to 35%, increase OB1 max cycle time, or move logic out of OB1
Login returns 403/401 intermittently Session cookie not reused Use cookie jar / Session object; verify session timeout (default 30 min)
0.5 s per call not reachable on S7-1200 Platform limit — no native API Migrate to S7-1500 or ET200SP and use the JSON-RPC API
TLS handshake dominates cycle Cold TLS per request Disable HTTPS on trusted OT segment, or enable keep-alive

Official References

FAQ

Is the S7-1500 web server actually faster than the S7-1200 for the same AWP page?

No, not for AWP pages. AWP performance is constrained by the firmware's single-threaded HTML render path, and a 5-request cycle lands in the same 8-10 s range on both platforms with default settings. The S7-1500 / ET200SP advantage is the built-in JSON-RPC API, which is not available on the S7-1200 and returns ~0.5 s per call instead of the 1.6-2.0 s AWP delivers.

What is the maximum value for Communication Load on an S7-1200?

50%. Raising it further is not permitted by TIA Portal and would risk OB1 starvation. In practice, 50% is the upper limit; 35% is a safer operating point that still drops the 5-request cycle to roughly 5-6 s.

Does enabling HTTPS on the S7-1200 add measurable latency to the web server cycle?

Yes — a cold TLS handshake adds 150-300 ms per new TCP connection. With HTTP keep-alive (one TCP connection, one login) the cost is paid once per cycle instead of five times, recovering roughly 0.5-1.0 s on a 5-request cycle. On an isolated OT network, disabling HTTPS and using HTTP only is a defensible optimization.

Can PUT/GET replace the web server for fast reads on the S7-1200?

Yes. PUT/GET on the S7-1200 (firmware V4.0+) returns single-tag values in 20-80 ms and bypasses the HTML renderer entirely. It is a better fit than AWP for tight REST loops, but it does require the customer to switch from HTTPS GET/POST to a PROFINET-side library (Snap7, libnodave, or a Siemens-commissioned OPC UA server).

Why does my write appear to be missing on the next read of the AWP page?

Because OB1 has not yet propagated the new tag value to the process image when the second read arrives. Either shorten the OB1 cycle time, insert a 1× OB1 sleep in the client between the write and the re-read, or move the tag out of any optimized data block access so it is read directly from the load memory.

Back to blog