Resolving S7-1200 Webserver AWP JavaScript Tag Write Errors

David Krause13 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

Resolving S7-1200 Webserver AWP JavaScript Tag Write Errors

The SIMATIC S7-1200 integrated web server allows HTML pages stored in a project-generated "www" data block to read and write PLC tags through Automation Web Programming (AWP) commands. A frequent engineering problem arises when developers try to construct AWP commands at runtime from JavaScript — for example, when capturing canvas mouse coordinates and pushing them into a global DB. The web server returns errors such as WebInt:PLCtag"Zmienne"wspolrzedne.x not found and the tag never updates, even though the HTML page loads, the JavaScript executes, and the project compiles without errors.

This reference documents the root cause of the failure, the correct AWP syntax, the limits of the S7-1200 web server, and the engineering solutions that work in current TIA Portal versions (V16, V17, V18, V19, V20).

Affected hardware: S7-1200 CPU family (including 1212C DC/DC/DC, 1212C DC/DC/Rly, 1212C AC/DC/Rly) from firmware V4.0 onward. The behavior described also applies to S7-1200 G2 (6AG1 series) web server. Enabling the Web server (Siemens manual).

1. Problem Description

A user HTML page hosted on the S7-1200 web server implements a freehand drawing canvas. Each mousemove event must push the cursor coordinates to two PLC real (or LReal) tags inside a global DB named Zmienne (Polish for "Variables") — wspolrzedne.x and wspolrzedne.y ("coordinates").

The JavaScript constructs strings that look like AWP commands and appends them to a hidden <div>:

// BROKEN — does not work
infox = "<!-- AWP_In_Variable Name='wspolrzednex' Use='"Zmienne"wspolrzedne.x'-->:=wspolrzednex:";
document.getElementById("PLC_COMMAND_DIV").innerHTML += infox;

The page loads, the drawing works, the script runs without console errors, and TIA Portal → Compile → Download to device succeeds. However, after regenerating the www blocks and downloading again, the CPU diagnostic buffer records:

WebInt:PLCtag"Zmienne"wspolrzedne.x not found
WebInt:PLCtag"Zmienne"wspolrzedne.y not found

Coordinate values never reach the PLC. The web page reads 0.0 on the next refresh.

2. Root Cause Analysis

The web server processes AWP commands only during the static HTML compilation step, when TIA Portal generates the www data blocks. Once the HTML is stored on the CPU, the runtime web server treats <!-- ... --> as a literal HTML comment, regardless of how it was inserted.

Three independent failures occur in the example code:

Failure Mechanism Effect
Dynamic AWP injection AWP commands are stripped from the generated www DBs; the runtime does not re-parse innerHTML as AWP directives. Tags are never registered with the web server.
Malformed Use= path The fully qualified tag path must be "DB_Name"."Tag" with no extra dot-separated segment. '"Zmienne"wspolrzedne.x' is parsed as a path element that does not exist. Diagnostic buffer error: PLCtag"Zmienne"wspolrzedne.x not found.
Wrong command for writing :=variable: is the read substitution (writes from PLC to HTML). AWP_In_Variable is the declaration command placed in the HTML <head>. No inbound binding is established.
Hard limit: The S7-1200 web server www DB is capped at 64 KB. Every AWP-tagged symbol costs header overhead per fragment HTML file, so a page with 100 individually-bound tags can exhaust the budget. This is the dominant reason static binding is required — dynamic generation cannot be supported because the runtime has no allocation path for new tag bindings.

3. AWP Command Reference

Use the following command set inside the HTML files of your "Webserver" project node. All commands appear as HTML comments — the browser ignores them, the TIA compiler interprets them.

Command Direction Purpose Location
<!-- AWP_In_Variable Name='"DB"."Tag"' --> PLC ← Browser Declares a writable tag (form input, hidden field) <head> or <body>
<!-- AWP_Out_Variable Name='"DB"."Tag"' --> PLC → Browser Declares a readable tag <head> or <body>
<!-- AWP_Enum_Def Name='MyEnum' Values='0="Off",1="On"' --> n/a Defines enum for drop-down lists <head>
<!-- AWP_Enum_Ref Name='MyEnum' Enum='MyEnum' --> n/a References enum on a tag With AWP_In_Variable
<!-- AWP_Start_Fragment --> / <!-- AWP_End_Fragment --> n/a Delimits an HTML fragment for repeated use Surrounding block
:="DB"."Tag": PLC → Browser Inline read substitution (writes value into HTML output) Inside tag attribute or text
:="DB"."Tag":= PLC ← Browser URL/parameter write target for HTTP GET writes Inside form action URL

The fully qualified tag name must be enclosed in single quotes and the inner double quotes must be escaped or written as raw ":

<!-- AWP_In_Variable Name='"Zmienne"."wspolrzedne"."x"' -->
<!-- AWP_In_Variable Name='"Zmienne"."wspolrzedne"."y"' -->

For structured tags, the AWP path uses dot notation. The example '"Zmienne"wspolrzedne.x' is missing the dot between the DB name and the structure instance and the dot between structure instance and member.

4. Why JavaScript Cannot Build AWP Commands

The web server architecture is split into two phases:

  1. Compile phase (TIA Portal): Scans the source HTML files for AWP comments. Builds a binding table that maps each tag to an offset in the generated www data block. The AWP commands themselves are then removed from the generated HTML before it is placed in the www DB.
  2. Runtime phase (CPU web server): Serves the static HTML. Substitutes read values for :=tag: markers. Writes values received in form posts to the registered bindings. Never re-parses the page.

When JavaScript executes element.innerHTML += "<!-- AWP_In_Variable ... -->", the browser's DOM inserts a comment node, but the S7-1200 web server has no listener for DOM mutations — it shipped the page bytes at request time and has no further involvement. The comment exists only in the browser memory of the client.

Even document.createComment(...) fails for the same reason: it inserts a DOM Comment node, not a binding directive. The web server is not the DOM.

5. Working Solutions

5.1 Solution A — Static binding with HTML input controls

Bind the coordinates to hidden form fields updated by JavaScript. The form is submitted through an HTTP GET or POST to the same page. The AWP read-write syntax handles the values.

HTML (in your fragment file draw.htm):

<html>
<head>
  <!-- AWP_In_Variable Name='"Zmienne"."wspolrzedne"."x"' -->
  <!-- AWP_In_Variable Name='"Zmienne"."wspolrzedne"."y"' -->
  <title>Coordinate Write</title>
</head>
<body>
  <form id="coordForm" method="POST" action="">
    <input type="hidden" name='"Zmienne"."wspolrzedne"."x"' id="xIn" value="0">
    <input type="hidden" name='"Zmienne"."wspolrzedne"."y"' id="yIn" value="0">
    <input type="submit" value="Push to PLC">
  </form>

  <canvas id="c" width="400" height="300" style="border:1px solid #000;"></canvas>
  <div id="PLC_COMMAND_DIV"></div>

  <script>
    var canvas = document.getElementById('c');
    var ctx = canvas.getContext('2d');
    var last = 0, Timefreq = 30;
    var tool = { started: false };

    canvas.addEventListener('mousedown', function(ev){ tool.started = true; ctx.beginPath(); ctx.moveTo(ev.offsetX, ev.offsetY); last = new Date().getTime(); });
    canvas.addEventListener('mouseup',   function(ev){ tool.started = false; });
    canvas.addEventListener('mouseleave',function(ev){ tool.started = false; });

    canvas.addEventListener('mousemove', function(ev){
      if (!tool.started) return;
      var now = new Date().getTime();
      if (now - last < Timefreq) return;
      last = now;
      ctx.lineTo(ev.offsetX, ev.offsetY);
      ctx.stroke();

      // Update the hidden inputs only — DO NOT inject AWP commands
      document.getElementById('xIn').value = ev.offsetX;
      document.getElementById('yIn').value = ev.offsetY;
    });

    // Optional: throttle form auto-submit to send coordinates every N ms
    setInterval(function(){
      if (tool.started) document.getElementById('coordForm').submit();
    }, 200);
  </script>
</body>
</html>

PLC data block Zmienne:

DATA_BLOCK "Zmienne"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
NON_RETAIN
  STRUCT
    wspolrzedne : STRUCT
      x : REAL;     // browser → PLC
      y : REAL;     // browser → PLC
    END_STRUCT;
  END_STRUCT;
END_DATA_BLOCK

For S7-1200 web access you must disable optimized block access (or use only single-element tags placed in a non-optimized DB) so the AWP binding offset is computable. Mark { S7_Optimized_Access := 'FALSE' } in the DB attributes or uncheck "Optimized block access" in the DB properties.

Security: The S7-1200 web server has no user authentication by default (it is configurable to use the CPU's user administration starting with firmware V4.4). Anyone on the network with the CPU IP can write arbitrary values to any AWP-bound tag. Validate ranges in your PLC logic before acting on the values. Enabling the Web server — Siemens manual.

5.2 Solution B — Manual GET request without form submit

Use XMLHttpRequest or fetch() to POST a form-encoded payload to the page URL. The web server accepts URL-encoded name=value pairs and writes them to AWP-bound tags.

function pushCoord(x, y) {
  var body = '"Zmienne"."wspolrzedne"."x"=' + encodeURIComponent(x)
           + '&"Zmienne"."wspolrzedne"."y"=' + encodeURIComponent(y);
  fetch('/draw.htm', {
    method: 'POST',
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    body: body,
    credentials: 'include'
  }).catch(function(err){ console.error('AWP write failed', err); });
}

For a one-variable write (e.g. boolean or integer), the GET form is shorter and fits the read-write marker syntax:

<a href="draw.htm? :="Zmienne"."wspolrzedne"."x":=>Set X</a>

For numeric ranges, encode the value directly in the URL after :=:

fetch('draw.htm?' + encodeURIComponent(':="Zmienne"."wspolrzedne"."x"') + '=' + x);

5.3 Solution C — TIA Portal V16+ Web API

From TIA Portal V16 onward, an HTTPS-based Web API is available on the S7-1200 web server. The API exposes each tag as a REST resource, so JavaScript can use fetch() against JSON endpoints without any AWP HTML trickery.

Enable the API: CPU Properties → Web server → Permitted users / API. Define a user with the Web API permission. The default base URL is https://<CPU-IP>>/api/ (or http:// if you have not enabled HTTPS).

JavaScript example:

async function setCoord(x, y) {
  const auth = btoa('webuser:webpassword');
  const headers = { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + auth };

  await fetch('https://192.168.0.10/api/v1/tags/Zmienne.wspolrzedne.x', {
    method: 'PATCH',
    headers: headers,
    body: JSON.stringify({ value: x })
  });
  await fetch('https://192.168.0.10/api/v1/tags/Zmienne.wspolrzedne.y', {
    method: 'PATCH',
    headers: headers,
    body: JSON.stringify({ value: y })
  });
}

Endpoints (firmware V4.5 / TIA V17+):

Method URL Effect
GET /api/v1/tags/{path} Read single tag (JSON)
GET /api/v1/tags?path={a}&path={b} Read multiple tags
PATCH /api/v1/tags/{path} with body {"value": n} Write single tag
POST /api/v1/tags with body listing paths/values Bulk write

The tag path uses dot notation: Zmienne.wspolrzedne.x (no DB quotes). For structured tags you must address the leaf. Optimized access is fully supported by the Web API, unlike AWP.

6. Step-by-Step Verification Procedure

  1. Verify DB accessibility. In the project tree, right-click Zmienne → Properties → Attributes → uncheck Optimized block access. Recompile. Confirm the offset column is populated in the DB editor.
  2. Validate AWP syntax. Open your .htm file in TIA Portal. Right-click → "Web server" → "Generate web DB". Any syntax error appears in the Inspector → Info tab.
  3. Download the www DB. Connect to the CPU, right-click the S7-1200 → Download to device → Software (all). Confirm the message Web DB generated successfully.
  4. Test the URL. In a browser, navigate to http://<CPU-IP>>/draw.htm. Confirm the page loads and the canvas is visible.
  5. Inspect the diagnostic buffer. In TIA Portal: Online → Online & Diagnostics → Diagnostic buffer. Any WebInt:PLCtag ... not found entry points to a misspelled path.
  6. Watch a tag in the watch table. Add "Zmienne"."wspolrzedne"."x" to a watch table. Move the mouse and trigger a form submit. The value should change in <1 s.
  7. Open the browser dev tools. Network tab → submit the form → inspect the POST body. It should contain %22Zmienne%22.%22wspolrzedne%22.%22x%22=123 (URL-encoded tag name = value).

7. Common Error Matrix

Symptom Cause Fix
WebInt:PLCtag"Zmienne"wspolrzedne.x not found Malformed Name or Use attribute in AWP Use Name='"Zmienne"."wspolrzedne"."x"' with quoted DB and structure segments
Page loads but values always zero AWP comment inside JavaScript string, not static HTML Move AWP into static <head>; use form inputs to carry values
Compile error Maximum size of web DB exceeded More than 64 KB of www content Split HTML into fragments, reduce static AWP bindings, or move to Web API
HTTP 401 on POST Web server user administration enabled but no login Disable protection, or send Authorization: Basic header with valid user
Browser shows page fine on PC, not on phone HTTPS-only mode forced in CPU Set Enable HTTPS in CPU web server properties or accept the certificate
JavaScript fetch blocked by CORS Web API and page served from different origins or no CORS Serve page from the CPU itself or use plain XHR; the CPU does not send CORS headers
Tags visible in Go online but AWP does not bind DB has Optimized block access enabled Disable optimization on the DB (or move tags to a non-optimized DB)

8. Memory Budget and Performance Notes

The S7-1200 web server stores all HTML in a single DB generated by TIA. The 64 KB cap is shared across all fragment files. Each AWP-bound input adds roughly 50–120 bytes of metadata in the binding table. A typical HMI with 50 inputs, 30 read displays, and 3 fragment files lands near 12–18 KB. Approaches that work cleanly:

  • Use a single page that loads fragment files via fetch() — each fragment has its own binding scope but ships in the same DB.
  • For dense numeric arrays, write a single tag of type ARRAY[0..99] OF REAL and bind one fragment template that iterates with JavaScript. The array costs one AWP binding; the loop costs nothing.
  • For canvas-style high-rate data (mouse moves at 60 Hz), do not POST every frame — buffer and submit at 5–10 Hz to avoid saturating the web server task.

The S7-1200 web server runs as a low-priority background task. Heavy write traffic increases CPU load and can extend OB1 cycle time if the project is small. Web API requests are processed sequentially per connection.

9. Best Practices for Production Web HMIs

  1. Bind only what you need. Avoid binding the entire DB. Each binding consumes DB memory and compile time.
  2. Validate in the PLC. A bound input is a remote-control surface. Add range checks and use the Error-checking and Range-checking options in the user program as recommended in the Siemens web server manual.
  3. Use the Web API for new projects (TIA V16+). It removes the 64 KB limit, supports optimized DBs, and gives JSON responses that are easier to parse than AWP substitutions.
  4. Force HTTPS. Web server authentication credentials and tag values cross the network in cleartext without it.
  5. Disable the web server when not needed. CPU Properties → Web server → uncheck Enable web server. The feature is not free at runtime.
  6. Do not place AWP commands in JavaScript strings. They are not interpreted. Plan bindings statically at compile time.
  7. Use the official S7-1200 G2 webserver video as a refresher for the new G2 generation's user interface: SIMATIC S7-1200 G2 Webserver Guide.

10. Cross-Reference: AWP vs. Web API vs. OPC UA

Feature AWP (HTML) Web API (REST/JSON) OPC UA
Minimum firmware V4.0 V4.4 (S7-1200 V16+) V4.4
Optimized DBs supported No (partial in V4.4) Yes Yes
Storage limit 64 KB www DB None (DB content only) None
Read latency (LAN) 10–50 ms 20–80 ms 10–30 ms
Authentication CPU user administration (V4.4+) Basic / Digest Certificate / user token
Best for Simple custom HMI in HTML/CSS Modern SPA, dashboards, mobile SCADA, IIoT, cross-vendor

11. Diagnostic Buffer Entry Decoder

Web server errors land in the diagnostic buffer with category "WebInt". Common entries:

Message text fragment Meaning Action
PLCtag ... not found AWP path is not in the binding table Check Name / Use quoting and DB accessibility
Web DB too large www DB > 64 KB Split fragments, remove unused AWP, move to Web API
Authentication failed Wrong or missing CPU user Configure user in CPU web server properties
HTTP request malformed Form post missing application/x-www-form-urlencoded Set Content-Type header in JavaScript
Method not allowed Web API endpoint does not accept the verb Use PATCH/GET/POST as listed in §5.3

12. Frequently Asked Questions

Why does my JavaScript-injected AWP_In_Variable not bind a PLC tag?

The S7-1200 web server parses AWP commands at compile time inside TIA Portal, not at runtime in the browser. AWP comments inserted via innerHTML or createComment() exist only in the browser DOM and are never seen by the web server. Declare all AWP commands as static comments in the HTML source files of the webserver project node.

What is the correct AWP_In_Variable syntax for a structured tag?

Use dot-separated quoted segments: <!-- AWP_In_Variable Name='"DB"."StructInstance"."Member"' -->. For example, Name='"Zmienne"."wspolrzedne"."x"'. The DB must have optimized access disabled for the binding to be resolved by older firmware.

Can I write to PLC tags from JavaScript without reloading the page?

Yes, use fetch() or XMLHttpRequest to POST a form-encoded body to the page URL with name=value pairs that match your AWP-bound input names, or use the TIA V16+ Web API with JSON PATCH requests to /api/v1/tags/{path}. Both approaches avoid a full page reload.

What is the maximum size of the S7-1200 webserver www DB?

64 KB across all HTML files, fragments, and AWP binding metadata. On S7-1200 G2 the cap is similar (varies by firmware; consult the CPU manual). For projects exceeding this, use the Web API or OPC UA instead of AWP.

Do I need to disable optimized block access for AWP bindings?

Yes, on classic S7-1200 firmware (V4.0–V4.3). Disable Optimized block access on the data block containing AWP-bound tags. From firmware V4.4 the Web API works with optimized blocks; AWP support for optimized blocks is partial and case-dependent.

How do I push high-frequency mouse coordinates from a canvas to the PLC?

Throttle the writes (5–10 Hz is realistic for the S7-1200 web server), and use a form submit or a Web API PATCH per coordinate pair. Avoid posting on every mousemove event — the web server task will saturate. Buffer coordinates on the client and submit in batches when needed.

Back to blog